diff mbox series

[v3,ARM,3/x] : MVE ACLE intrinsics framework patch.

Message ID DBBPR08MB4775BF4A8C8127959AF7F23C9BFF0@DBBPR08MB4775.eurprd08.prod.outlook.com
State New
Headers show
Series [v3,ARM,3/x] : MVE ACLE intrinsics framework patch. | expand

Commit Message

Srinath Parvathaneni March 10, 2020, 6:19 p.m. UTC
Hello Kyrill,

This patch addresses all the comments in patch version v2.
(version v2) https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540417.html

####


Hello,

This patch is part of MVE ACLE intrinsics framework.

The patch supports the use of emulation for the single-precision arithmetic
operations for MVE. This changes are to support the MVE ACLE intrinsics which
operates on vector floating point arithmetic operations.

Please refer to Arm reference manual [1] for more details.
[1] https://developer.arm.com/docs/ddi0553/latest

Regression tested on target arm-none-eabi and armeb-none-eabi and found no regressions.

Ok for trunk?

Thanks,
Srinath.

gcc/ChangeLog:

2020-03-06  Andre Vieira  <andre.simoesdiasvieira@arm.com>
	    Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

	* config/arm/arm.c (arm_libcall_uses_aapcs_base): Modify function to add
	emulator calls for dobule precision arithmetic operations for MVE.

2020-03-06  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

	* gcc.target/arm/mve/intrinsics/mve_libcall1.c: New test.
	* gcc.target/arm/mve/intrinsics/mve_libcall2.c: Likewise.


###############     Attachment also inlined for ease of reply    ###############
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c28a475629c7fbad48730beed5550e0cffdf2e1b..40db35a2a8b6dedb4f536b4995e80c8b9a38b588 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -5754,9 +5754,25 @@ arm_libcall_uses_aapcs_base (const_rtx libcall)
       /* Values from double-precision helper functions are returned in core
 	 registers if the selected core only supports single-precision
 	 arithmetic, even if we are using the hard-float ABI.  The same is
-	 true for single-precision helpers, but we will never be using the
-	 hard-float ABI on a CPU which doesn't support single-precision
-	 operations in hardware.  */
+	 true for single-precision helpers except in case of MVE, because in
+	 MVE we will be using the hard-float ABI on a CPU which doesn't support
+	 single-precision operations in hardware.  In MVE the following check
+	 enables use of emulation for the single-precision arithmetic
+	 operations.  */
+      if (TARGET_HAVE_MVE)
+	{
+	  add_libcall (libcall_htab, optab_libfunc (add_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (sdiv_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (smul_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (neg_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (sub_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (eq_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (lt_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (le_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (ge_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (gt_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (unord_optab, SFmode));
+	}
       add_libcall (libcall_htab, optab_libfunc (add_optab, DFmode));
       add_libcall (libcall_htab, optab_libfunc (sdiv_optab, DFmode));
       add_libcall (libcall_htab, optab_libfunc (smul_optab, DFmode));
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
new file mode 100644
index 0000000000000000000000000000000000000000..f89301228c577291fc3095420df1937e1a0c7104
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile  } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+mve -mfloat-abi=hard -mthumb -mfpu=auto" } */
+
+float
+foo (float a, float b, float c)
+{
+  return a + b + c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fadd" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fadd" 2 } } */
+
+float
+foo1 (float a, float b, float c)
+{
+  return a - b - c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fsub" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fsub" 2 } } */
+
+float
+foo2 (float a, float b, float c)
+{
+  return a * b * c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fmul" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fmul" 2 } } */
+
+float
+foo3 (float b, float c)
+{
+  return b / c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fdiv" }  } */
+
+int
+foo4 (float b, float c)
+{
+  return b < c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmplt" }  } */
+
+int
+foo5 (float b, float c)
+{
+  return b > c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpgt" }  } */
+
+int
+foo6 (float b, float c)
+{
+  return b != c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpeq" }  } */
+
+int
+foo7 (float b, float c)
+{
+  return b == c;
+}
+
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fcmpeq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
new file mode 100644
index 0000000000000000000000000000000000000000..d13cb175f409e817fd935cffedcb5747eee2f22b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
@@ -0,0 +1,70 @@
+/* { dg-do compile  } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+mve -mfloat-abi=hard -mthumb -mfpu=auto" } */
+
+double
+foo (double a, double b, double c)
+{
+  return a + b + c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dadd" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dadd" 2 } } */
+
+double
+foo1 (double a, double b, double c)
+{
+  return a - b - c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dsub" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dsub" 2 } } */
+
+double
+foo2 (double a, double b, double c)
+{
+  return a * b * c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dmul" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dmul" 2 } } */
+
+double
+foo3 (double b, double c)
+{
+  return b / c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_ddiv" }  } */
+
+int
+foo4 (double b, double c)
+{
+  return b < c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmplt" }  } */
+
+int
+foo5 (double b, double c)
+{
+  return b > c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpgt" }  } */
+
+int
+foo6 (double b, double c)
+{
+  return b != c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpeq" }  } */
+
+int
+foo7 (double b, double c)
+{
+  return b == c;
+}
+
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dcmpeq" 2 } } */

Comments

Kyrill Tkachov March 12, 2020, 11:18 a.m. UTC | #1
Hi Srinath,

On 3/10/20 6:19 PM, Srinath Parvathaneni wrote:
> Hello Kyrill,
>
> This patch addresses all the comments in patch version v2.
> (version v2) 
> https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540417.html
>
> ####
>
>
> Hello,
>
> This patch is part of MVE ACLE intrinsics framework.
>
> The patch supports the use of emulation for the single-precision 
> arithmetic
> operations for MVE. This changes are to support the MVE ACLE 
> intrinsics which
> operates on vector floating point arithmetic operations.
>
> Please refer to Arm reference manual [1] for more details.
> [1] https://developer.arm.com/docs/ddi0553/latest
>
> Regression tested on target arm-none-eabi and armeb-none-eabi and 
> found no regressions.
>
> Ok for trunk?
>
> Thanks,
> Srinath.
>
> gcc/ChangeLog:
>
> 2020-03-06  Andre Vieira <andre.simoesdiasvieira@arm.com>
>             Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
>         * config/arm/arm.c (arm_libcall_uses_aapcs_base): Modify 
> function to add
>         emulator calls for dobule precision arithmetic operations for MVE.
>
> 2020-03-06  Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
>         * gcc.target/arm/mve/intrinsics/mve_libcall1.c: New test.
>         * gcc.target/arm/mve/intrinsics/mve_libcall2.c: Likewise.
>
>
> ###############     Attachment also inlined for ease of reply    
> ###############
>
>
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 
> c28a475629c7fbad48730beed5550e0cffdf2e1b..40db35a2a8b6dedb4f536b4995e80c8b9a38b588 
> 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -5754,9 +5754,25 @@ arm_libcall_uses_aapcs_base (const_rtx libcall)
>        /* Values from double-precision helper functions are returned 
> in core
>           registers if the selected core only supports single-precision
>           arithmetic, even if we are using the hard-float ABI.  The 
> same is
> -        true for single-precision helpers, but we will never be using the
> -        hard-float ABI on a CPU which doesn't support single-precision
> -        operations in hardware.  */
> +        true for single-precision helpers except in case of MVE, 
> because in
> +        MVE we will be using the hard-float ABI on a CPU which 
> doesn't support
> +        single-precision operations in hardware.  In MVE the 
> following check
> +        enables use of emulation for the single-precision arithmetic
> +        operations.  */
> +      if (TARGET_HAVE_MVE)
> +       {
> +         add_libcall (libcall_htab, optab_libfunc (add_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (sdiv_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (smul_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (neg_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (sub_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (eq_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (lt_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (le_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (ge_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (gt_optab, SFmode));
> +         add_libcall (libcall_htab, optab_libfunc (unord_optab, SFmode));
> +       }
>        add_libcall (libcall_htab, optab_libfunc (add_optab, DFmode));
>        add_libcall (libcall_htab, optab_libfunc (sdiv_optab, DFmode));
>        add_libcall (libcall_htab, optab_libfunc (smul_optab, DFmode));
> diff --git 
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c 
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..f89301228c577291fc3095420df1937e1a0c7104
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
> @@ -0,0 +1,70 @@
> +/* { dg-do compile  } */
> +/* { dg-require-effective-target arm_v8_1m_mve_ok } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve 
> -mfloat-abi=hard -mthumb -mfpu=auto" } */
> +
> +float
> +foo (float a, float b, float c)
> +{
> +  return a + b + c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fadd" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_fadd" 2 } } */


What is the point of repeating the scan-assembler directives here? The 
first scan-assembler should be redundant given the scan-assembler-times ?

Otherwise ok.

Thanks,

Kyrill


> +
> +float
> +foo1 (float a, float b, float c)
> +{
> +  return a - b - c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fsub" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_fsub" 2 } } */
> +
> +float
> +foo2 (float a, float b, float c)
> +{
> +  return a * b * c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fmul" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_fmul" 2 } } */
> +
> +float
> +foo3 (float b, float c)
> +{
> +  return b / c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fdiv" }  } */
> +
> +int
> +foo4 (float b, float c)
> +{
> +  return b < c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fcmplt" }  } */
> +
> +int
> +foo5 (float b, float c)
> +{
> +  return b > c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpgt" }  } */
> +
> +int
> +foo6 (float b, float c)
> +{
> +  return b != c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpeq" }  } */
> +
> +int
> +foo7 (float b, float c)
> +{
> +  return b == c;
> +}
> +
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_fcmpeq" 2 } } */
> diff --git 
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c 
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..d13cb175f409e817fd935cffedcb5747eee2f22b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
> @@ -0,0 +1,70 @@
> +/* { dg-do compile  } */
> +/* { dg-require-effective-target arm_v8_1m_mve_ok } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve 
> -mfloat-abi=hard -mthumb -mfpu=auto" } */
> +
> +double
> +foo (double a, double b, double c)
> +{
> +  return a + b + c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dadd" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_dadd" 2 } } */
> +
> +double
> +foo1 (double a, double b, double c)
> +{
> +  return a - b - c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dsub" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_dsub" 2 } } */
> +
> +double
> +foo2 (double a, double b, double c)
> +{
> +  return a * b * c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dmul" }  } */
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_dmul" 2 } } */
> +
> +double
> +foo3 (double b, double c)
> +{
> +  return b / c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_ddiv" }  } */
> +
> +int
> +foo4 (double b, double c)
> +{
> +  return b < c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dcmplt" }  } */
> +
> +int
> +foo5 (double b, double c)
> +{
> +  return b > c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpgt" }  } */
> +
> +int
> +foo6 (double b, double c)
> +{
> +  return b != c;
> +}
> +
> +/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpeq" }  } */
> +
> +int
> +foo7 (double b, double c)
> +{
> +  return b == c;
> +}
> +
> +/* { dg-final { scan-assembler-times "bl\\t__aeabi_dcmpeq" 2 } } */
>
diff mbox series

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c28a475629c7fbad48730beed5550e0cffdf2e1b..40db35a2a8b6dedb4f536b4995e80c8b9a38b588 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -5754,9 +5754,25 @@  arm_libcall_uses_aapcs_base (const_rtx libcall)
       /* Values from double-precision helper functions are returned in core
 	 registers if the selected core only supports single-precision
 	 arithmetic, even if we are using the hard-float ABI.  The same is
-	 true for single-precision helpers, but we will never be using the
-	 hard-float ABI on a CPU which doesn't support single-precision
-	 operations in hardware.  */
+	 true for single-precision helpers except in case of MVE, because in
+	 MVE we will be using the hard-float ABI on a CPU which doesn't support
+	 single-precision operations in hardware.  In MVE the following check
+	 enables use of emulation for the single-precision arithmetic
+	 operations.  */
+      if (TARGET_HAVE_MVE)
+	{
+	  add_libcall (libcall_htab, optab_libfunc (add_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (sdiv_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (smul_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (neg_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (sub_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (eq_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (lt_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (le_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (ge_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (gt_optab, SFmode));
+	  add_libcall (libcall_htab, optab_libfunc (unord_optab, SFmode));
+	}
       add_libcall (libcall_htab, optab_libfunc (add_optab, DFmode));
       add_libcall (libcall_htab, optab_libfunc (sdiv_optab, DFmode));
       add_libcall (libcall_htab, optab_libfunc (smul_optab, DFmode));
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
new file mode 100644
index 0000000000000000000000000000000000000000..f89301228c577291fc3095420df1937e1a0c7104
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall1.c
@@ -0,0 +1,70 @@ 
+/* { dg-do compile  } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+mve -mfloat-abi=hard -mthumb -mfpu=auto" } */
+
+float
+foo (float a, float b, float c)
+{
+  return a + b + c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fadd" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fadd" 2 } } */
+
+float
+foo1 (float a, float b, float c)
+{
+  return a - b - c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fsub" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fsub" 2 } } */
+
+float
+foo2 (float a, float b, float c)
+{
+  return a * b * c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fmul" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fmul" 2 } } */
+
+float
+foo3 (float b, float c)
+{
+  return b / c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fdiv" }  } */
+
+int
+foo4 (float b, float c)
+{
+  return b < c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmplt" }  } */
+
+int
+foo5 (float b, float c)
+{
+  return b > c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpgt" }  } */
+
+int
+foo6 (float b, float c)
+{
+  return b != c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_fcmpeq" }  } */
+
+int
+foo7 (float b, float c)
+{
+  return b == c;
+}
+
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_fcmpeq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
new file mode 100644
index 0000000000000000000000000000000000000000..d13cb175f409e817fd935cffedcb5747eee2f22b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_libcall2.c
@@ -0,0 +1,70 @@ 
+/* { dg-do compile  } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+mve -mfloat-abi=hard -mthumb -mfpu=auto" } */
+
+double
+foo (double a, double b, double c)
+{
+  return a + b + c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dadd" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dadd" 2 } } */
+
+double
+foo1 (double a, double b, double c)
+{
+  return a - b - c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dsub" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dsub" 2 } } */
+
+double
+foo2 (double a, double b, double c)
+{
+  return a * b * c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dmul" }  } */
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dmul" 2 } } */
+
+double
+foo3 (double b, double c)
+{
+  return b / c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_ddiv" }  } */
+
+int
+foo4 (double b, double c)
+{
+  return b < c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmplt" }  } */
+
+int
+foo5 (double b, double c)
+{
+  return b > c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpgt" }  } */
+
+int
+foo6 (double b, double c)
+{
+  return b != c;
+}
+
+/* { dg-final { scan-assembler "bl\\t__aeabi_dcmpeq" }  } */
+
+int
+foo7 (double b, double c)
+{
+  return b == c;
+}
+
+/* { dg-final { scan-assembler-times "bl\\t__aeabi_dcmpeq" 2 } } */