diff mbox

[AArch64] Add support for vectorizable standard math patterns.

Message ID 1354035099-30521-1-git-send-email-james.greenhalgh@arm.com
State New
Headers show

Commit Message

James Greenhalgh Nov. 27, 2012, 4:51 p.m. UTC
Hi,

This patch adds support for vectorizing across some of the rounding
functions in the C math library to the AArch64 back-end.

In particular, we add support for vectorizing across:

ceil (), ceilf (), lceil (),
floor (), floorf (), lfloor (),
round (), roundf (),
nearbyint (), nearbyintf (),
trunc (), truncf ()

We add testcases ensuring that each of the expected functions are
vectorized. As the i386 and rs6000 backends both ostensibly support
these optimisations we add these tests to the generic testsuites, but
only wire them up for AArch64. As a target may support any subset of
these vectorizations we need a check_effective_target macro for
each of them.

Because of this change to the generic test code I've CCed Janis
Johnson and Mike Stump.

Is this patch OK to commit?

Thanks,
James

---
gcc/

2012-11-27  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc/config/aarch64/aarch64-builtins.c
	(aarch64_builtin_vectorized_function): New.
	* gcc/config/aarch64/aarch64-protos.h
	(aarch64_builtin_vectorized_function): Declare.
	* gcc/config/aarch64/aarch64-simd-builtins.def (frintz, frintp): Add.
	(frintm, frinti, frintx, frinta, fcvtzs, fcvtzu): Likewise.
	(fcvtas, fcvtau, fcvtps, fcvtpu, fcvtms, fcvtmu): Likewise.
	* gcc/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.
	* gcc/config/aarch64/aarch64.c (TARGET_VECTORIZE_BUILTINS): Define.
	(TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION): Likewise.
	* gcc/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.
	* gcc/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/

2012-11-27  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc/testsuite/gcc.dg/vect/vect-rounding-btrunc.c: New test.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-btruncf.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-ceil.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-ceilf.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-floor.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-floorf.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-lceil.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-lfloor.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyint.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyintf.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-round.c: Likewise.
	* gcc/testsuite/gcc.dg/vect/vect-rounding-roundf.c: Likewise.
	* gcc/testsuite/lib/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.

Comments

Mike Stump Nov. 27, 2012, 8:47 p.m. UTC | #1
On Nov 27, 2012, at 8:51 AM, James Greenhalgh <james.greenhalgh@arm.com> wrote:
> In particular, we add support for vectorizing across:
> 
> ceil (), ceilf (), lceil (),

> We add testcases ensuring that each of the expected functions are
> vectorized. As the i386 and rs6000 backends both ostensibly support
> these optimisations we add these tests to the generic testsuites, but
> only wire them up for AArch64. As a target may support any subset of
> these vectorizations we need a check_effective_target macro for
> each of them.
> 
> Because of this change to the generic test code I've CCed Janis
> Johnson and Mike Stump.

Gosh…  leaves a bad taste in my mouth.    I see why you did it that way…  So, let me just ping folks, anyone see a better way to do this?  If no one admits to having a better solution, I'll approve it.  Let's give them a few days to come up with something concrete, if they fail, Ok.
Ramana Radhakrishnan Nov. 27, 2012, 11:04 p.m. UTC | #2
On Tue, Nov 27, 2012 at 8:47 PM, Mike Stump <mikestump@comcast.net> wrote:
> On Nov 27, 2012, at 8:51 AM, James Greenhalgh <james.greenhalgh@arm.com> wrote:
>> In particular, we add support for vectorizing across:
>>
>> ceil (), ceilf (), lceil (),
>
>> We add testcases ensuring that each of the expected functions are
>> vectorized. As the i386 and rs6000 backends both ostensibly support
>> these optimisations we add these tests to the generic testsuites, but
>> only wire them up for AArch64. As a target may support any subset of
>> these vectorizations we need a check_effective_target macro for
>> each of them.
>>
>> Because of this change to the generic test code I've CCed Janis
>> Johnson and Mike Stump.
>
> Gosh…  leaves a bad taste in my mouth.    I see why you did it that way…
> So, let me just ping folks, anyone see a better way to do this?  If no one admits to having a better solution, I'll approve
>  it.  Let's give them a few days to come up with something concrete, if they fail, Ok.

If it's any consolation I expect the ARM port to use a subset of
these, because in the AArch32 world on v8 we only have the single
precision vector variants of these instructions and not the double
precision vector variants once we can get hold of the intrinsic decls
we need :) . So, if someone's thinking who's going to be a consumer of
a subset of these, here's one port that's likely to need this.

That doesn't preclude finding a better way of doing this :)

regards
Ramana
Marcus Shawcroft Dec. 3, 2012, 4:43 p.m. UTC | #3
On 27/11/12 20:47, Mike Stump wrote:
> On Nov 27, 2012, at 8:51 AM, James Greenhalgh <james.greenhalgh@arm.com> wrote:
>> In particular, we add support for vectorizing across:
>>
>> ceil (), ceilf (), lceil (),
>
>> We add testcases ensuring that each of the expected functions are
>> vectorized. As the i386 and rs6000 backends both ostensibly support
>> these optimisations we add these tests to the generic testsuites, but
>> only wire them up for AArch64. As a target may support any subset of
>> these vectorizations we need a check_effective_target macro for
>> each of them.
>>
>> Because of this change to the generic test code I've CCed Janis
>> Johnson and Mike Stump.
>
> Gosh…  leaves a bad taste in my mouth.    I see why you did it that way…  So, let me just ping folks, anyone see a better way to do this?  If no one admits to having a better solution, I'll approve it.  Let's give them a few days to come up with something concrete, if they fail, Ok.
>


Mike, Are you happy to go with the proposal from James or would like to 
give folk more time to think this one over?

Cheers
/Marcus
Mike Stump Dec. 3, 2012, 7:19 p.m. UTC | #4
On Dec 3, 2012, at 8:43 AM, Marcus Shawcroft <Marcus.Shawcroft@arm.com> wrote:
> Mike, Are you happy to go with the proposal from James or would like to give folk more time to think this one over?

Good to go.  If people want to improve it, if they see a way, then can submit a patch anytime they want.  I didn't see anyone lay down a clearly better way to do this.
Marcus Shawcroft Dec. 4, 2012, 3 p.m. UTC | #5
On 27/11/12 16:51, James Greenhalgh wrote:
>
> Hi,
>
> This patch adds support for vectorizing across some of the rounding
> functions in the C math library to the AArch64 back-end.
>
> In particular, we add support for vectorizing across:
>
> ceil (), ceilf (), lceil (),
> floor (), floorf (), lfloor (),
> round (), roundf (),
> nearbyint (), nearbyintf (),
> trunc (), truncf ()
>
> We add testcases ensuring that each of the expected functions are
> vectorized. As the i386 and rs6000 backends both ostensibly support
> these optimisations we add these tests to the generic testsuites, but
> only wire them up for AArch64. As a target may support any subset of
> these vectorizations we need a check_effective_target macro for
> each of them.
>
> Because of this change to the generic test code I've CCed Janis
> Johnson and Mike Stump.
>
> Is this patch OK to commit?

OK
/Marcus
James Greenhalgh Dec. 5, 2012, 2:14 p.m. UTC | #6
> > Is this patch OK to commit?
> 
> OK
> /Marcus

Thanks Marcus,

I've also back-ported this to AArch64-4.7-branch.
The back-port was clean and passed a regression run on
aarch64-none-elf with no regressions.

Thanks,
James
Richard Earnshaw Dec. 17, 2012, 2:23 p.m. UTC | #7
On 27/11/12 20:47, Mike Stump wrote:
> On Nov 27, 2012, at 8:51 AM, James Greenhalgh <james.greenhalgh@arm.com> wrote:
>> In particular, we add support for vectorizing across:
>>
>> ceil (), ceilf (), lceil (),
>
>> We add testcases ensuring that each of the expected functions are
>> vectorized. As the i386 and rs6000 backends both ostensibly support
>> these optimisations we add these tests to the generic testsuites, but
>> only wire them up for AArch64. As a target may support any subset of
>> these vectorizations we need a check_effective_target macro for
>> each of them.
>>
>> Because of this change to the generic test code I've CCed Janis
>> Johnson and Mike Stump.
>
> Gosh…  leaves a bad taste in my mouth.    I see why you did it that way…  So, let me just ping folks, anyone see a better way to do this?  If no one admits to having a better solution, I'll approve it.  Let's give them a few days to come up with something concrete, if they fail, Ok.
>


I've been pondering this one for a bit.  I wonder if having a single 
function

check_effective_target_vect_libcall(func)

where func is the name of the function you needed to check, might be 
cleaner.

The idea is that the one function might access an array (set up on the 
first call) and then just use "info exists et_vect_libcalls(func)" to do 
the body of the check.

Not entirely sure my expect foo is good enough to code this up, though.

R.
Janis Johnson Dec. 17, 2012, 6:34 p.m. UTC | #8
On 12/17/2012 06:23 AM, Richard Earnshaw wrote:
> On 27/11/12 20:47, Mike Stump wrote:
>> On Nov 27, 2012, at 8:51 AM, James Greenhalgh <james.greenhalgh@arm.com> wrote:
>>> In particular, we add support for vectorizing across:
>>>
>>> ceil (), ceilf (), lceil (),
>>
>>> We add testcases ensuring that each of the expected functions are
>>> vectorized. As the i386 and rs6000 backends both ostensibly support
>>> these optimisations we add these tests to the generic testsuites, but
>>> only wire them up for AArch64. As a target may support any subset of
>>> these vectorizations we need a check_effective_target macro for
>>> each of them.
>>>
>>> Because of this change to the generic test code I've CCed Janis
>>> Johnson and Mike Stump.
>>
>> Gosh…  leaves a bad taste in my mouth.    I see why you did it that way…  So, let me just ping folks, anyone see a better way to do this?  If no one admits to having a better solution, I'll approve it.  Let's give them a few days to come up with something concrete, if they fail, Ok.
>>
> 
> 
> I've been pondering this one for a bit.  I wonder if having a single 
> function
> 
> check_effective_target_vect_libcall(func)
> 
> where func is the name of the function you needed to check, might be 
> cleaner.
> 
> The idea is that the one function might access an array (set up on the 
> first call) and then just use "info exists et_vect_libcalls(func)" to do 
> the body of the check.
> 
> Not entirely sure my expect foo is good enough to code this up, though.
> 
> R.
> 

I suspect that the Tcl code to support an array would end up being
messier and less maintainable.

Janis
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 2cdda0f..a683afd 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -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
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index ab84257..2110970 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -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 */
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 2e3c4e1..b344120 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -206,3 +206,21 @@ 
   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)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index b3d01c1..8c9ceac 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1240,6 +1240,46 @@ 
    (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")
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6241ba5..d60402d 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -6845,6 +6845,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
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 17f024f..b59d53d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2325,117 +2325,27 @@ 
 ;; 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>")]
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 7a1cdc8..31bc977 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -453,6 +453,9 @@ 
 (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
 ;; -------------------------------------------------------------------
@@ -647,6 +650,12 @@ 
 (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.
 ;; -------------------------------------------------------------------
@@ -729,3 +738,19 @@ 
 (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")])
+
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
index 0000000..7432fe7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-btrunc.c
@@ -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
index 0000000..0835e1b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-btruncf.c
@@ -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
index 0000000..a430690
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-ceil.c
@@ -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
index 0000000..4d00924
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-ceilf.c
@@ -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
index 0000000..8f1c9ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-floor.c
@@ -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
index 0000000..a68c2ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-floorf.c
@@ -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
index 0000000..b4ed236
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-lceil.c
@@ -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
index 0000000..5a36631
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-lfloor.c
@@ -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
index 0000000..572dbd3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyint.c
@@ -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
index 0000000..73ca7de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-nearbyintf.c
@@ -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
index 0000000..c298bbb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-round.c
@@ -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
index 0000000..362b9d6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-rounding-roundf.c
@@ -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" } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 5935346..59d854f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -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 { } {