[AARCH64] Add support for vectorizable standard math patterns.
authorJames Greenhalgh <james.greenhalgh@arm.com>
Wed, 5 Dec 2012 10:34:31 +0000 (10:34 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Wed, 5 Dec 2012 10:34:31 +0000 (10:34 +0000)
gcc/

* config/aarch64/aarch64-builtins.c
(aarch64_builtin_vectorized_function): New.
* config/aarch64/aarch64-protos.h
(aarch64_builtin_vectorized_function): Declare.
* config/aarch64/aarch64-simd-builtins.def (frintz, frintp): Add.
(frintm, frinti, frintx, frinta, fcvtzs, fcvtzu): Likewise.
(fcvtas, fcvtau, fcvtps, fcvtpu, fcvtms, fcvtmu): Likewise.
* config/aarch64/aarch64-simd.md
(aarch64_frint_<frint_suffix><mode>): New.
(<frint_pattern><mode>2): Likewise.
(aarch64_fcvt<frint_suffix><su><mode>): Likewise.
(l<fcvt_pattern><su_optab><fcvt_target><VDQF:mode>2): Likewise.
* config/aarch64/aarch64.c (TARGET_VECTORIZE_BUILTINS): Define.
(TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION): Likewise.
* config/aarch64/aarch64.md
(btrunc<mode>2, ceil<mode>2, floor<mode>2)
(round<mode>2, rint<mode>2, nearbyint<mode>2): Consolidate as...
(<frint_pattern><mode>2): ...this.
(lceil<su_optab><mode><mode>2, lfloor<su_optab><mode><mode>2)
(lround<su_optab><mode><mode>2)
(lrint<su_optab><mode><mode>2): Consolidate as...
(l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2): ... this.
* config/aarch64/iterators.md (fcvt_target): New.
(FCVT_TARGET): Likewise.
(FRINT): Likewise.
(FCVT): Likewise.
(frint_pattern): Likewise.
(frint_suffix): Likewise.
(fcvt_pattern): Likewise.

gcc/testsuite/

* gcc.dg/vect/vect-rounding-btrunc.c: New test.
* gcc.dg/vect/vect-rounding-btruncf.c: Likewise.
* gcc.dg/vect/vect-rounding-ceil.c: Likewise.
* gcc.dg/vect/vect-rounding-ceilf.c: Likewise.
* gcc.dg/vect/vect-rounding-floor.c: Likewise.
* gcc.dg/vect/vect-rounding-floorf.c: Likewise.
* gcc.dg/vect/vect-rounding-lceil.c: Likewise.
* gcc.dg/vect/vect-rounding-lfloor.c: Likewise.
* gcc.dg/vect/vect-rounding-nearbyint.c: Likewise.
* gcc.dg/vect/vect-rounding-nearbyintf.c: Likewise.
* gcc.dg/vect/vect-rounding-round.c: Likewise.
* gcc.dg/vect/vect-rounding-roundf.c: Likewise.
* target-supports.exp
(check_effective_target_vect_call_btrunc): New.
(check_effective_target_vect_call_btruncf): Likewise.
(check_effective_target_vect_call_ceil): Likewise.
(check_effective_target_vect_call_ceilf): Likewise.
(check_effective_target_vect_call_floor): Likewise.
(check_effective_target_vect_call_floorf): Likewise.
(check_effective_target_vect_call_lceil): Likewise.
(check_effective_target_vect_call_lfloor): Likewise.
(check_effective_target_vect_call_nearbyint): Likewise.
(check_effective_target_vect_call_nearbyintf): Likewise.
(check_effective_target_vect_call_round): Likewise.
(check_effective_target_vect_call_roundf): Likewise.

From-SVN: r194197

22 files changed:
gcc/ChangeLog
gcc/config/aarch64/aarch64-builtins.c
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64-simd-builtins.def
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-rounding-btrunc.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-btruncf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-ceil.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-ceilf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-floor.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-floorf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-lceil.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-lfloor.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyint.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyintf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-round.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-rounding-roundf.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index 5bbe08b6c7b8b37b8ab88fb7081a9072a28a9074..aa10fd35db8e5b75b929be2efe297b156281cf52 100644 (file)
@@ -1,3 +1,35 @@
+2012-12-05  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * config/aarch64/aarch64-builtins.c
+       (aarch64_builtin_vectorized_function): New.
+       * config/aarch64/aarch64-protos.h
+       (aarch64_builtin_vectorized_function): Declare.
+       * config/aarch64/aarch64-simd-builtins.def (frintz, frintp): Add.
+       (frintm, frinti, frintx, frinta, fcvtzs, fcvtzu): Likewise.
+       (fcvtas, fcvtau, fcvtps, fcvtpu, fcvtms, fcvtmu): Likewise.
+       * config/aarch64/aarch64-simd.md
+       (aarch64_frint_<frint_suffix><mode>): New.
+       (<frint_pattern><mode>2): Likewise.
+       (aarch64_fcvt<frint_suffix><su><mode>): Likewise.
+       (l<fcvt_pattern><su_optab><fcvt_target><VDQF:mode>2): Likewise.
+       * config/aarch64/aarch64.c (TARGET_VECTORIZE_BUILTINS): Define.
+       (TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION): Likewise.
+       * config/aarch64/aarch64.md
+       (btrunc<mode>2, ceil<mode>2, floor<mode>2)
+       (round<mode>2, rint<mode>2, nearbyint<mode>2): Consolidate as...
+       (<frint_pattern><mode>2): ...this.
+       (lceil<su_optab><mode><mode>2, lfloor<su_optab><mode><mode>2)
+       (lround<su_optab><mode><mode>2)
+       (lrint<su_optab><mode><mode>2): Consolidate as...
+       (l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2): ... this.
+       * config/aarch64/iterators.md (fcvt_target): New.
+       (FCVT_TARGET): Likewise.
+       (FRINT): Likewise.
+       (FCVT): Likewise.
+       (frint_pattern): Likewise.
+       (frint_suffix): Likewise.
+       (fcvt_pattern): Likewise.
+
 2012-12-05  Steven Bosscher  <steven@gcc.gnu.org>
 
        * passes.c (pass_init_dump_file): Only open a clean graph dump file if
index 2cdda0fc03c41bb0ada98cce0c0931324bc02064..a683afd0bb6afee3663194342e1396b009019f78 100644 (file)
@@ -1221,3 +1221,70 @@ aarch64_expand_builtin (tree exp,
 
   return NULL_RTX;
 }
+
+tree
+aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
+{
+  enum machine_mode in_mode, out_mode;
+  int in_n, out_n;
+
+  if (TREE_CODE (type_out) != VECTOR_TYPE
+      || TREE_CODE (type_in) != VECTOR_TYPE)
+    return NULL_TREE;
+
+  out_mode = TYPE_MODE (TREE_TYPE (type_out));
+  out_n = TYPE_VECTOR_SUBPARTS (type_out);
+  in_mode = TYPE_MODE (TREE_TYPE (type_in));
+  in_n = TYPE_VECTOR_SUBPARTS (type_in);
+
+#undef AARCH64_CHECK_BUILTIN_MODE
+#define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
+#define AARCH64_FIND_FRINT_VARIANT(N) \
+  (AARCH64_CHECK_BUILTIN_MODE (2, D) \
+    ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2df] \
+    : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
+       ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v4sf] \
+       : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
+          ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2sf] \
+          : NULL_TREE)))
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
+      switch (fn)
+       {
+#undef AARCH64_CHECK_BUILTIN_MODE
+#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
+  (out_mode == N##Fmode && out_n == C \
+   && in_mode == N##Fmode && in_n == C)
+       case BUILT_IN_FLOOR:
+       case BUILT_IN_FLOORF:
+         return AARCH64_FIND_FRINT_VARIANT (frintm);
+       case BUILT_IN_CEIL:
+       case BUILT_IN_CEILF:
+         return AARCH64_FIND_FRINT_VARIANT (frintp);
+       case BUILT_IN_TRUNC:
+       case BUILT_IN_TRUNCF:
+         return AARCH64_FIND_FRINT_VARIANT (frintz);
+       case BUILT_IN_ROUND:
+       case BUILT_IN_ROUNDF:
+         return AARCH64_FIND_FRINT_VARIANT (frinta);
+       case BUILT_IN_NEARBYINT:
+       case BUILT_IN_NEARBYINTF:
+         return AARCH64_FIND_FRINT_VARIANT (frinti);
+#undef AARCH64_CHECK_BUILTIN_MODE
+#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
+  (out_mode == N##Imode && out_n == C \
+   && in_mode == N##Fmode && in_n == C)
+       case BUILT_IN_LFLOOR:
+         return AARCH64_FIND_FRINT_VARIANT (fcvtms);
+       case BUILT_IN_LCEIL:
+         return AARCH64_FIND_FRINT_VARIANT (fcvtps);
+       default:
+         return NULL_TREE;
+      }
+    }
+
+  return NULL_TREE;
+}
+#undef AARCH64_CHECK_BUILTIN_MODE
+#undef AARCH64_FIND_FRINT_VARIANT
index ab84257d54c3ff99d8e636a62f7ea2acd638c666..2110970c3588b06c92e49355c8f74390e59b3bcd 100644 (file)
@@ -236,4 +236,9 @@ rtx aarch64_expand_builtin (tree exp,
                            int ignore ATTRIBUTE_UNUSED);
 tree aarch64_builtin_decl (unsigned, bool ATTRIBUTE_UNUSED);
 
+tree
+aarch64_builtin_vectorized_function (tree fndecl,
+                                    tree type_out,
+                                    tree type_in);
+
 #endif /* GCC_AARCH64_PROTOS_H */
index 2e3c4e1ca5faf7a5ce0f619a6c29af5ef45c314d..b344120ae90ce16b4512fbf3b96246a2a3d378fe 100644 (file)
   BUILTIN_VDQ_BHSI (BINOP, smin)
   BUILTIN_VDQ_BHSI (BINOP, umax)
   BUILTIN_VDQ_BHSI (BINOP, umin)
+
+  /* Implemented by aarch64_frint<frint_suffix><mode>.  */
+  BUILTIN_VDQF (UNOP, frintz)
+  BUILTIN_VDQF (UNOP, frintp)
+  BUILTIN_VDQF (UNOP, frintm)
+  BUILTIN_VDQF (UNOP, frinti)
+  BUILTIN_VDQF (UNOP, frintx)
+  BUILTIN_VDQF (UNOP, frinta)
+
+  /* Implemented by aarch64_fcvt<frint_suffix><su><mode>.  */
+  BUILTIN_VDQF (UNOP, fcvtzs)
+  BUILTIN_VDQF (UNOP, fcvtzu)
+  BUILTIN_VDQF (UNOP, fcvtas)
+  BUILTIN_VDQF (UNOP, fcvtau)
+  BUILTIN_VDQF (UNOP, fcvtps)
+  BUILTIN_VDQF (UNOP, fcvtpu)
+  BUILTIN_VDQF (UNOP, fcvtms)
+  BUILTIN_VDQF (UNOP, fcvtmu)
index b3d01c1919905d8d5a73a3e3ac2965870de5c35b..8c9ceaca7e2dbf473ab319d1a2acdf4d9f152062 100644 (file)
    (set_attr "simd_mode" "<MODE>")]
 )
 
+(define_insn "aarch64_frint<frint_suffix><mode>"
+  [(set (match_operand:VDQF 0 "register_operand" "=w")
+       (unspec:VDQF [(match_operand:VDQF 1 "register_operand" "w")]
+                     FRINT))]
+  "TARGET_SIMD"
+  "frint<frint_suffix>\\t%0.<Vtype>, %1.<Vtype>"
+  [(set_attr "simd_type" "simd_frint")
+   (set_attr "simd_mode" "<MODE>")]
+)
+
+;; Vector versions of the floating-point frint patterns.
+;; Expands to btrunc, ceil, floor, nearbyint, rint, round.
+(define_expand "<frint_pattern><mode>2"
+  [(set (match_operand:VDQF 0 "register_operand")
+       (unspec:VDQF [(match_operand:VDQF 1 "register_operand")]
+                     FRINT))]
+  "TARGET_SIMD"
+  {})
+
+(define_insn "aarch64_fcvt<frint_suffix><su><mode>"
+  [(set (match_operand:<FCVT_TARGET> 0 "register_operand" "=w")
+       (FIXUORS:<FCVT_TARGET> (unspec:<FCVT_TARGET>
+                              [(match_operand:VDQF 1 "register_operand" "w")]
+                              FCVT)))]
+  "TARGET_SIMD"
+  "fcvt<frint_suffix><su>\\t%0.<Vtype>, %1.<Vtype>"
+  [(set_attr "simd_type" "simd_fcvti")
+   (set_attr "simd_mode" "<MODE>")]
+)
+
+;; Vector versions of the fcvt standard patterns.
+;; Expands to lbtrunc, lround, lceil, lfloor
+(define_expand "l<fcvt_pattern><su_optab><fcvt_target><VDQF:mode>2"
+  [(set (match_operand:<FCVT_TARGET> 0 "register_operand")
+       (FIXUORS:<FCVT_TARGET> (unspec:<FCVT_TARGET>
+                              [(match_operand:VDQF 1 "register_operand")]
+                              FCVT)))]
+  "TARGET_SIMD"
+  {})
+
 (define_insn "aarch64_vmls<mode>"
   [(set (match_operand:VDQF 0 "register_operand" "=w")
        (minus:VDQF (match_operand:VDQF 1 "register_operand" "0")
index 445cd4fc23ac48335cb4b4a27338fc7a51802f2e..971e71f1ef4ea3bd2749854b473a821f12274d92 100644 (file)
@@ -6879,6 +6879,13 @@ aarch64_c_mode_for_suffix (char suffix)
 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE aarch64_preferred_simd_mode
 
+#undef TARGET_VECTORIZE_BUILTINS
+#define TARGET_VECTORIZE_BUILTINS
+
+#undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
+#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
+  aarch64_builtin_vectorized_function
+
 /* Section anchor support.  */
 
 #undef TARGET_MIN_ANCHOR_OFFSET
index 17f024fa40f46cee2ce63b40ea67a7269c1e482e..b59d53df86ac4de7056ac86eeec66c0f24442513 100644 (file)
 ;; Floating-point intrinsics
 ;; -------------------------------------------------------------------
 
-;; trunc - nothrow
+;; frint floating-point round to integral standard patterns.
+;; Expands to btrunc, ceil, floor, nearbyint, rint, round.
 
-(define_insn "btrunc<mode>2"
+(define_insn "<frint_pattern><mode>2"
   [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTZ))]
+       (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
+        FRINT))]
   "TARGET_FLOAT"
-  "frintz\\t%<s>0, %<s>1"
+  "frint<frint_suffix>\\t%<s>0, %<s>1"
   [(set_attr "v8type" "frint")
    (set_attr "mode" "<MODE>")]
 )
 
-(define_insn "*lbtrunc<su_optab><GPF:mode><GPI:mode>2"
+;; frcvt floating-point round to integer and convert standard patterns.
+;; Expands to lbtrunc, lceil, lfloor, lround.
+(define_insn "l<fcvt_pattern><su_optab><GPF:mode><GPI:mode>2"
   [(set (match_operand:GPI 0 "register_operand" "=r")
-        (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-                     UNSPEC_FRINTZ)))]
+       (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
+                     FCVT)))]
   "TARGET_FLOAT"
-  "fcvtz<su>\\t%<GPI:w>0, %<GPF:s>1"
-  [(set_attr "v8type" "fcvtf2i")
-   (set_attr "mode" "<GPF:MODE>")
-   (set_attr "mode2" "<GPI:MODE>")]
-)
-
-;; ceil - nothrow
-
-(define_insn "ceil<mode>2"
-  [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTP))]
-  "TARGET_FLOAT"
-  "frintp\\t%<s>0, %<s>1"
-  [(set_attr "v8type" "frint")
-   (set_attr "mode" "<MODE>")]
-)
-
-(define_insn "lceil<su_optab><GPF:mode><GPI:mode>2"
-  [(set (match_operand:GPI 0 "register_operand" "=r")
-        (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-                     UNSPEC_FRINTP)))]
-  "TARGET_FLOAT"
-  "fcvtp<su>\\t%<GPI:w>0, %<GPF:s>1"
-  [(set_attr "v8type" "fcvtf2i")
-   (set_attr "mode" "<GPF:MODE>")
-   (set_attr "mode2" "<GPI:MODE>")]
-)
-
-;; floor - nothrow
-
-(define_insn "floor<mode>2"
-  [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTM))]
-  "TARGET_FLOAT"
-  "frintm\\t%<s>0, %<s>1"
-  [(set_attr "v8type" "frint")
-   (set_attr "mode" "<MODE>")]
-)
-
-(define_insn "lfloor<su_optab><GPF:mode><GPI:mode>2"
-  [(set (match_operand:GPI 0 "register_operand" "=r")
-        (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-                     UNSPEC_FRINTM)))]
-  "TARGET_FLOAT"
-  "fcvtm<su>\\t%<GPI:w>0, %<GPF:s>1"
-  [(set_attr "v8type" "fcvtf2i")
-   (set_attr "mode" "<GPF:MODE>")
-   (set_attr "mode2" "<GPI:MODE>")]
-)
-
-;; nearbyint - nothrow
-
-(define_insn "nearbyint<mode>2"
-  [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTI))]
-  "TARGET_FLOAT"
-  "frinti\\t%<s>0, %<s>1"
-  [(set_attr "v8type" "frint")
-   (set_attr "mode" "<MODE>")]
-)
-
-;; rint
-
-(define_insn "rint<mode>2"
-  [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTX))]
-  "TARGET_FLOAT"
-  "frintx\\t%<s>0, %<s>1"
-  [(set_attr "v8type" "frint")
-   (set_attr "mode" "<MODE>")]
-)
-
-;; round - nothrow
-
-(define_insn "round<mode>2"
-  [(set (match_operand:GPF 0 "register_operand" "=w")
-        (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-        UNSPEC_FRINTA))]
-  "TARGET_FLOAT"
-  "frinta\\t%<s>0, %<s>1"
-  [(set_attr "v8type" "frint")
-   (set_attr "mode" "<MODE>")]
-)
-
-(define_insn "lround<su_optab><GPF:mode><GPI:mode>2"
-  [(set (match_operand:GPI 0 "register_operand" "=r")
-        (FIXUORS:GPI (unspec:GPF [(match_operand:GPF 1 "register_operand" "w")]
-                     UNSPEC_FRINTA)))]
-  "TARGET_FLOAT"
-  "fcvta<su>\\t%<GPI:w>0, %<GPF:s>1"
+  "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF:s>1"
   [(set_attr "v8type" "fcvtf2i")
    (set_attr "mode" "<GPF:MODE>")
    (set_attr "mode2" "<GPI:MODE>")]
index 7a1cdc895351a71e3f0f4d4803b2879bcc8c16eb..31bc97748fdb59b7e84546932cb324a987cecc19 100644 (file)
 (define_mode_attr atomic_sfx
   [(QI "b") (HI "h") (SI "") (DI "")])
 
+(define_mode_attr fcvt_target [(V2DF "v2di") (V4SF "v4si") (V2SF "v2si")])
+(define_mode_attr FCVT_TARGET [(V2DF "V2DI") (V4SF "V4SI") (V2SF "V2SI")])
+
 ;; -------------------------------------------------------------------
 ;; Code Iterators
 ;; -------------------------------------------------------------------
 (define_int_iterator VCMP_U [UNSPEC_CMHS UNSPEC_CMHI UNSPEC_CMTST])
 
 
+(define_int_iterator FRINT [UNSPEC_FRINTZ UNSPEC_FRINTP UNSPEC_FRINTM
+                            UNSPEC_FRINTI UNSPEC_FRINTX UNSPEC_FRINTA])
+
+(define_int_iterator FCVT [UNSPEC_FRINTZ UNSPEC_FRINTP UNSPEC_FRINTM
+                           UNSPEC_FRINTA])
+
 ;; -------------------------------------------------------------------
 ;; Int Iterators Attributes.
 ;; -------------------------------------------------------------------
 (define_int_attr offsetlr [(UNSPEC_SSLI        "1") (UNSPEC_USLI "1")
                           (UNSPEC_SSRI "0") (UNSPEC_USRI "0")])
 
+;; Standard pattern names for floating-point rounding instructions.
+(define_int_attr frint_pattern [(UNSPEC_FRINTZ "btrunc")
+                               (UNSPEC_FRINTP "ceil")
+                               (UNSPEC_FRINTM "floor")
+                               (UNSPEC_FRINTI "nearbyint")
+                               (UNSPEC_FRINTX "rint")
+                               (UNSPEC_FRINTA "round")])
+
+;; frint suffix for floating-point rounding instructions.
+(define_int_attr frint_suffix [(UNSPEC_FRINTZ "z") (UNSPEC_FRINTP "p")
+                              (UNSPEC_FRINTM "m") (UNSPEC_FRINTI "i")
+                              (UNSPEC_FRINTX "x") (UNSPEC_FRINTA "a")])
+
+(define_int_attr fcvt_pattern [(UNSPEC_FRINTZ "btrunc") (UNSPEC_FRINTA "round")
+                              (UNSPEC_FRINTP "ceil") (UNSPEC_FRINTM "floor")])
+
index 5c363d064be31c7fc03f9c900b834528dfb9b595..0bba403e0c5ec23bbc26d70bd3aa8d7ddeb2189d 100644 (file)
@@ -1,3 +1,31 @@
+2012-12-05  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * gcc.dg/vect/vect-rounding-btrunc.c: New test.
+       * gcc.dg/vect/vect-rounding-btruncf.c: Likewise.
+       * gcc.dg/vect/vect-rounding-ceil.c: Likewise.
+       * gcc.dg/vect/vect-rounding-ceilf.c: Likewise.
+       * gcc.dg/vect/vect-rounding-floor.c: Likewise.
+       * gcc.dg/vect/vect-rounding-floorf.c: Likewise.
+       * gcc.dg/vect/vect-rounding-lceil.c: Likewise.
+       * gcc.dg/vect/vect-rounding-lfloor.c: Likewise.
+       * gcc.dg/vect/vect-rounding-nearbyint.c: Likewise.
+       * gcc.dg/vect/vect-rounding-nearbyintf.c: Likewise.
+       * gcc.dg/vect/vect-rounding-round.c: Likewise.
+       * gcc.dg/vect/vect-rounding-roundf.c: Likewise.
+       * target-supports.exp
+       (check_effective_target_vect_call_btrunc): New.
+       (check_effective_target_vect_call_btruncf): Likewise.
+       (check_effective_target_vect_call_ceil): Likewise.
+       (check_effective_target_vect_call_ceilf): Likewise.
+       (check_effective_target_vect_call_floor): Likewise.
+       (check_effective_target_vect_call_floorf): Likewise.
+       (check_effective_target_vect_call_lceil): Likewise.
+       (check_effective_target_vect_call_lfloor): Likewise.
+       (check_effective_target_vect_call_nearbyint): Likewise.
+       (check_effective_target_vect_call_nearbyintf): Likewise.
+       (check_effective_target_vect_call_round): Likewise.
+       (check_effective_target_vect_call_roundf): Likewise.
+
 2012-12-05  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/51238
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-btrunc.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-btrunc.c
new file mode 100644 (file)
index 0000000..7432fe7
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_btrunc } */
+
+#define N 32
+
+void
+foo (double *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_trunc (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_btrunc } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-btruncf.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-btruncf.c
new file mode 100644 (file)
index 0000000..0835e1b
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_call_btruncf } */
+
+#define N 32
+
+void
+foo (float *output, float *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_truncf (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_btruncf } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-ceil.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-ceil.c
new file mode 100644 (file)
index 0000000..a430690
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_ceil } */
+
+#define N 32
+
+void
+foo (double *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_ceil (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_ceil } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-ceilf.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-ceilf.c
new file mode 100644 (file)
index 0000000..4d00924
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_call_ceilf } */
+
+#define N 32
+
+void
+foo (float *output, float *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_ceilf (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_ceilf } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-floor.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-floor.c
new file mode 100644 (file)
index 0000000..8f1c9ec
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_floor } */
+
+#define N 32
+
+void
+foo (double *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_floor (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_floor } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-floorf.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-floorf.c
new file mode 100644 (file)
index 0000000..a68c2ec
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_call_floorf } */
+
+#define N 32
+
+void
+foo (float *output, float *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_floorf (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_floorf } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-lceil.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-lceil.c
new file mode 100644 (file)
index 0000000..b4ed236
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_lceil } */
+
+#define N 32
+
+void
+foo (long *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_lceil (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_lceil } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-lfloor.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-lfloor.c
new file mode 100644 (file)
index 0000000..5a36631
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_lfloor } */
+
+#define N 32
+
+void
+foo (long *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_lfloor (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_lfloor } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyint.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyint.c
new file mode 100644 (file)
index 0000000..572dbd3
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_nearbyint } */
+
+#define N 32
+
+void
+foo (double *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_nearbyint (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_nearbyint } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyintf.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyintf.c
new file mode 100644 (file)
index 0000000..73ca7de
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_call_nearbyintf } */
+
+#define N 32
+
+void
+foo (float *output, float *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_nearbyintf (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_nearbyintf } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-round.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-round.c
new file mode 100644 (file)
index 0000000..c298bbb
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_call_round } */
+
+#define N 32
+
+void
+foo (double *output, double *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_round (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_round } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-rounding-roundf.c b/gcc/testsuite/gcc.dg/vect/vect-rounding-roundf.c
new file mode 100644 (file)
index 0000000..362b9d6
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_call_roundf } */
+
+#define N 32
+
+void
+foo (float *output, float *input)
+{
+  int i = 0;
+  /* Vectorizable.  */
+  for (i = 0; i < N; i++)
+    output[i] = __builtin_roundf (input[i]);
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_call_roundf } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 5935346cc654ad4061a8dd04e9d4623b1bb8f208..59d854f1d6c4a0a0f04112ddabe5e07d39df2959 100644 (file)
@@ -3925,6 +3925,222 @@ proc check_effective_target_vect_call_lrint { } {
     return $et_vect_call_lrint
 }
 
+# Return 1 if the target supports vector btrunc calls.
+
+proc check_effective_target_vect_call_btrunc { } {
+    global et_vect_call_btrunc_saved
+
+    if [info exists et_vect_call_btrunc_saved] {
+       verbose "check_effective_target_vect_call_btrunc: using cached result" 2
+    } else {
+       set et_vect_call_btrunc_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_btrunc_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_btrunc: returning $et_vect_call_btrunc_saved" 2
+    return $et_vect_call_btrunc_saved
+}
+
+# Return 1 if the target supports vector btruncf calls.
+
+proc check_effective_target_vect_call_btruncf { } {
+    global et_vect_call_btruncf_saved
+
+    if [info exists et_vect_call_btruncf_saved] {
+       verbose "check_effective_target_vect_call_btruncf: using cached result" 2
+    } else {
+       set et_vect_call_btruncf_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_btruncf_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_btruncf: returning $et_vect_call_btruncf_saved" 2
+    return $et_vect_call_btruncf_saved
+}
+
+# Return 1 if the target supports vector ceil calls.
+
+proc check_effective_target_vect_call_ceil { } {
+    global et_vect_call_ceil_saved
+
+    if [info exists et_vect_call_ceil_saved] {
+       verbose "check_effective_target_vect_call_ceil: using cached result" 2
+    } else {
+       set et_vect_call_ceil_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_ceil_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_ceil: returning $et_vect_call_ceil_saved" 2
+    return $et_vect_call_ceil_saved
+}
+
+# Return 1 if the target supports vector ceilf calls.
+
+proc check_effective_target_vect_call_ceilf { } {
+    global et_vect_call_ceilf_saved
+
+    if [info exists et_vect_call_ceilf_saved] {
+       verbose "check_effective_target_vect_call_ceilf: using cached result" 2
+    } else {
+       set et_vect_call_ceilf_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_ceilf_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_ceilf: returning $et_vect_call_ceilf_saved" 2
+    return $et_vect_call_ceilf_saved
+}
+
+# Return 1 if the target supports vector floor calls.
+
+proc check_effective_target_vect_call_floor { } {
+    global et_vect_call_floor_saved
+
+    if [info exists et_vect_call_floor_saved] {
+       verbose "check_effective_target_vect_call_floor: using cached result" 2
+    } else {
+       set et_vect_call_floor_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_floor_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_floor: returning $et_vect_call_floor_saved" 2
+    return $et_vect_call_floor_saved
+}
+
+# Return 1 if the target supports vector floorf calls.
+
+proc check_effective_target_vect_call_floorf { } {
+    global et_vect_call_floorf_saved
+
+    if [info exists et_vect_call_floorf_saved] {
+       verbose "check_effective_target_vect_call_floorf: using cached result" 2
+    } else {
+       set et_vect_call_floorf_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_floorf_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_floorf: returning $et_vect_call_floorf_saved" 2
+    return $et_vect_call_floorf_saved
+}
+
+# Return 1 if the target supports vector lceil calls.
+
+proc check_effective_target_vect_call_lceil { } {
+    global et_vect_call_lceil_saved
+
+    if [info exists et_vect_call_lceil_saved] {
+       verbose "check_effective_target_vect_call_lceil: using cached result" 2
+    } else {
+       set et_vect_call_lceil_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_lceil_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_lceil: returning $et_vect_call_lceil_saved" 2
+    return $et_vect_call_lceil_saved
+}
+
+# Return 1 if the target supports vector lfloor calls.
+
+proc check_effective_target_vect_call_lfloor { } {
+    global et_vect_call_lfloor_saved
+
+    if [info exists et_vect_call_lfloor_saved] {
+       verbose "check_effective_target_vect_call_lfloor: using cached result" 2
+    } else {
+       set et_vect_call_lfloor_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_lfloor_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_lfloor: returning $et_vect_call_lfloor_saved" 2
+    return $et_vect_call_lfloor_saved
+}
+
+# Return 1 if the target supports vector nearbyint calls.
+
+proc check_effective_target_vect_call_nearbyint { } {
+    global et_vect_call_nearbyint_saved
+
+    if [info exists et_vect_call_nearbyint_saved] {
+       verbose "check_effective_target_vect_call_nearbyint: using cached result" 2
+    } else {
+       set et_vect_call_nearbyint_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_nearbyint_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_nearbyint: returning $et_vect_call_nearbyint_saved" 2
+    return $et_vect_call_nearbyint_saved
+}
+
+# Return 1 if the target supports vector nearbyintf calls.
+
+proc check_effective_target_vect_call_nearbyintf { } {
+    global et_vect_call_nearbyintf_saved
+
+    if [info exists et_vect_call_nearbyintf_saved] {
+       verbose "check_effective_target_vect_call_nearbyintf: using cached result" 2
+    } else {
+       set et_vect_call_nearbyintf_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_nearbyintf_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_nearbyintf: returning $et_vect_call_nearbyintf_saved" 2
+    return $et_vect_call_nearbyintf_saved
+}
+
+# Return 1 if the target supports vector round calls.
+
+proc check_effective_target_vect_call_round { } {
+    global et_vect_call_round_saved
+
+    if [info exists et_vect_call_round_saved] {
+       verbose "check_effective_target_vect_call_round: using cached result" 2
+    } else {
+       set et_vect_call_round_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_round_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_round: returning $et_vect_call_round_saved" 2
+    return $et_vect_call_round_saved
+}
+
+# Return 1 if the target supports vector roundf calls.
+
+proc check_effective_target_vect_call_roundf { } {
+    global et_vect_call_roundf_saved
+
+    if [info exists et_vect_call_roundf_saved] {
+       verbose "check_effective_target_vect_call_roundf: using cached result" 2
+    } else {
+       set et_vect_call_roundf_saved 0
+       if { [istarget aarch64*-*-*] } {
+         set et_vect_call_roundf_saved 1
+       }
+    }
+
+    verbose "check_effective_target_vect_call_roundf: returning $et_vect_call_roundf_saved" 2
+    return $et_vect_call_roundf_saved
+}
+
 # Return 1 if the target supports section-anchors
 
 proc check_effective_target_section_anchors { } {