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.simoesdiasvie...@arm.com> Srinath Parvathaneni <srinath.parvathan...@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.parvathan...@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 } } */
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 } } */