Implement asrl and sqrshrl using the new MVE builtins framework.

The patch adds a testcase calling asrl (value, -10) to make sure the
compiler keeps the asrl instruction: before this patch, it would be
interpreted as undefined behavior and return 0.

gcc/ChangeLog:

        * config/arm/arm-mve-builtins-base.cc (enum which_scalar_shift):
        Add ss_ASRL, ss_SQRSHRL, and ss_SQRSHRL_SAT48 entries.
        (class mve_function_scalar_shift): Add support for ss_ASRL,
        ss_SQRSHRL, and ss_SQRSHRL_SAT48.
        (asrl, sqrshrl, sqrshrl_sat48): New.
        * config/arm/arm-mve-builtins-base.def (lsll, uqrshll)
        (uqrshll_sat48): New.
        * config/arm/arm-mve-builtins-base.h (lsll, uqrshll)
        (uqrshll_sat48): New.
        * config/arm/arm-mve-builtins-shapes.cc (scalar_s64_shift): New.
        * config/arm/arm-mve-builtins-shapes.h: (scalar_s64_shift): New.
        * config/arm/arm_mve.h (uqrshll): Delete.
        (uqrshll_sat48): Delete.
        (lsll): Delete.
        (__arm_lsll): Delete.
        (__arm_uqrshll): Delete.
        (__arm_uqrshll_sat48): Delete.
        * config/arm/mve.md (mve_uqrshll_sat<supf>_di): Add '@' prefix.

gcc/testsuite/ChangeLog:
        * gcc.target/arm/mve/intrinsics/asrl-negative-shift.c: New test.
---
 gcc/config/arm/arm-mve-builtins-base.cc       | 18 +++++++++++
 gcc/config/arm/arm-mve-builtins-base.def      |  3 ++
 gcc/config/arm/arm-mve-builtins-base.h        |  3 ++
 gcc/config/arm/arm-mve-builtins-shapes.cc     | 15 ++++++++++
 gcc/config/arm/arm-mve-builtins-shapes.h      |  1 +
 gcc/config/arm/arm_mve.h                      | 24 ---------------
 gcc/config/arm/mve.md                         |  2 +-
 .../arm/mve/intrinsics/asrl-negative-shift.c  | 30 +++++++++++++++++++
 8 files changed, 71 insertions(+), 25 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/arm/mve/intrinsics/asrl-negative-shift.c

diff --git a/gcc/config/arm/arm-mve-builtins-base.cc 
b/gcc/config/arm/arm-mve-builtins-base.cc
index 9157f99afb8..14986a8a13d 100644
--- a/gcc/config/arm/arm-mve-builtins-base.cc
+++ b/gcc/config/arm/arm-mve-builtins-base.cc
@@ -1244,7 +1244,10 @@ public:
 
 /* Map the function directly to the appropriate scalar shift builtin.  */
 enum which_scalar_shift {
+  ss_ASRL,
   ss_LSLL,
+  ss_SQRSHRL,
+  ss_SQRSHRL_SAT48,
   ss_UQRSHLL,
   ss_UQRSHLL_SAT48
 };
@@ -1267,10 +1270,22 @@ public:
 
     switch (m_scalar_shift)
       {
+      case ss_ASRL:
+       code = CODE_FOR_mve_asrl;
+       break;
+
       case ss_LSLL:
        code = CODE_FOR_mve_lsll;
        break;
 
+      case ss_SQRSHRL:
+       code = code_for_mve_sqrshrl_sat_di (SQRSHRL_64);
+       break;
+
+      case ss_SQRSHRL_SAT48:
+       code = code_for_mve_sqrshrl_sat_di (SQRSHRL_48);
+       break;
+
       case ss_UQRSHLL:
        code = code_for_mve_uqrshll_sat_di (UQRSHLL_64);
        break;
@@ -1454,7 +1469,10 @@ namespace arm_mve {
    (-1, -1, UNSPEC##_F,                                                        
\
     -1, -1, UNSPEC##_P_F))
 
+FUNCTION (asrl, mve_function_scalar_shift, (ss_ASRL))
 FUNCTION (lsll, mve_function_scalar_shift, (ss_LSLL))
+FUNCTION (sqrshrl, mve_function_scalar_shift, (ss_SQRSHRL))
+FUNCTION (sqrshrl_sat48, mve_function_scalar_shift, (ss_SQRSHRL_SAT48))
 FUNCTION (uqrshll, mve_function_scalar_shift, (ss_UQRSHLL))
 FUNCTION (uqrshll_sat48, mve_function_scalar_shift, (ss_UQRSHLL_SAT48))
 FUNCTION_PRED_P_S_U (vabavq, VABAVQ)
diff --git a/gcc/config/arm/arm-mve-builtins-base.def 
b/gcc/config/arm/arm-mve-builtins-base.def
index e6c262dafec..6ecb05e877b 100644
--- a/gcc/config/arm/arm-mve-builtins-base.def
+++ b/gcc/config/arm/arm-mve-builtins-base.def
@@ -18,7 +18,10 @@
    <http://www.gnu.org/licenses/>.  */
 
 #define REQUIRES_FLOAT false
+DEF_MVE_FUNCTION (asrl, scalar_s64_shift, none, none)
 DEF_MVE_FUNCTION (lsll, scalar_u64_shift, none, none)
+DEF_MVE_FUNCTION (sqrshrl, scalar_s64_shift, none, none)
+DEF_MVE_FUNCTION (sqrshrl_sat48, scalar_s64_shift, none, none)
 DEF_MVE_FUNCTION (uqrshll, scalar_u64_shift, none, none)
 DEF_MVE_FUNCTION (uqrshll_sat48, scalar_u64_shift, none, none)
 DEF_MVE_FUNCTION (vabavq, binary_acca_int32, all_integer, p_or_none)
diff --git a/gcc/config/arm/arm-mve-builtins-base.h 
b/gcc/config/arm/arm-mve-builtins-base.h
index 8041764997c..2f047008573 100644
--- a/gcc/config/arm/arm-mve-builtins-base.h
+++ b/gcc/config/arm/arm-mve-builtins-base.h
@@ -23,7 +23,10 @@
 namespace arm_mve {
 namespace functions {
 
+extern const function_base *const asrl;
 extern const function_base *const lsll;
+extern const function_base *const sqrshrl;
+extern const function_base *const sqrshrl_sat48;
 extern const function_base *const uqrshll;
 extern const function_base *const uqrshll_sat48;
 extern const function_base *const vabavq;
diff --git a/gcc/config/arm/arm-mve-builtins-shapes.cc 
b/gcc/config/arm/arm-mve-builtins-shapes.cc
index 779978acda8..41e656e0861 100644
--- a/gcc/config/arm/arm-mve-builtins-shapes.cc
+++ b/gcc/config/arm/arm-mve-builtins-shapes.cc
@@ -1723,6 +1723,21 @@ struct mvn_def : public overloaded_base<0>
 };
 SHAPE (mvn)
 
+/* int64_t foo(int64_t, int32_t)
+
+   Example: asrl
+   int64_t [__arm_]arsl(int64_t value, int32_t shift)  */
+struct scalar_s64_shift_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group,
+        bool preserve_user_namespace) const override
+  {
+    build_all (b, "ss64,ss64,ss32", group, MODE_none, preserve_user_namespace);
+  }
+};
+SHAPE (scalar_s64_shift)
+
 /* uint64_t foo(uint64_t, int32_t)
 
    Example: lsll.
diff --git a/gcc/config/arm/arm-mve-builtins-shapes.h 
b/gcc/config/arm/arm-mve-builtins-shapes.h
index e630fb27ce0..1841a8f7b22 100644
--- a/gcc/config/arm/arm-mve-builtins-shapes.h
+++ b/gcc/config/arm/arm-mve-builtins-shapes.h
@@ -67,6 +67,7 @@ namespace arm_mve
     extern const function_shape *const load_ext_gather_offset;
     extern const function_shape *const load_gather_base;
     extern const function_shape *const mvn;
+    extern const function_shape *const scalar_s64_shift;
     extern const function_shape *const scalar_u64_shift;
     extern const function_shape *const setq_lane;
     extern const function_shape *const store;
diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h
index 9381a3e5d06..704a04eba45 100644
--- a/gcc/config/arm/arm_mve.h
+++ b/gcc/config/arm/arm_mve.h
@@ -59,8 +59,6 @@
 #define vuninitializedq_f16(void) __arm_vuninitializedq_f16(void)
 #define vuninitializedq_f32(void) __arm_vuninitializedq_f32(void)
 #define sqrshr(__p0, __p1) __arm_sqrshr(__p0, __p1)
-#define sqrshrl(__p0, __p1) __arm_sqrshrl(__p0, __p1)
-#define sqrshrl_sat48(__p0, __p1) __arm_sqrshrl_sat48(__p0, __p1)
 #define sqshl(__p0, __p1) __arm_sqshl(__p0, __p1)
 #define sqshll(__p0, __p1) __arm_sqshll(__p0, __p1)
 #define srshr(__p0, __p1) __arm_srshr(__p0, __p1)
@@ -70,30 +68,8 @@
 #define uqshll(__p0, __p1) __arm_uqshll(__p0, __p1)
 #define urshr(__p0, __p1) __arm_urshr(__p0, __p1)
 #define urshrl(__p0, __p1) __arm_urshrl(__p0, __p1)
-#define asrl(__p0, __p1) __arm_asrl(__p0, __p1)
 #endif
 
-__extension__ extern __inline int64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-__arm_asrl (int64_t value, int32_t shift)
-{
-  return (value >> shift);
-}
-
-__extension__ extern __inline int64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-__arm_sqrshrl (int64_t value, int32_t shift)
-{
-  return __builtin_mve_sqrshrl_sat64_di (value, shift);
-}
-
-__extension__ extern __inline int64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-__arm_sqrshrl_sat48 (int64_t value, int32_t shift)
-{
-  return __builtin_mve_sqrshrl_sat48_di (value, shift);
-}
-
 __extension__ extern __inline uint64_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 __arm_uqshll (uint64_t value, const int shift)
diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
index fa6fe392936..e9de7f09dbb 100644
--- a/gcc/config/arm/mve.md
+++ b/gcc/config/arm/mve.md
@@ -4279,7 +4279,7 @@ (define_insn "@mve_uqrshll_sat<supf>_di"
 ;;
 ;; [sqrshrl_di]
 ;;
-(define_insn "mve_sqrshrl_sat<supf>_di"
+(define_insn "@mve_sqrshrl_sat<supf>_di"
   [(set (match_operand:DI 0 "arm_low_register_operand" "=l")
        (unspec:DI [(match_operand:DI 1 "arm_low_register_operand" "0")
                    (match_operand:SI 2 "register_operand" "r")]
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/asrl-negative-shift.c 
b/gcc/testsuite/gcc.target/arm/mve/intrinsics/asrl-negative-shift.c
new file mode 100644
index 00000000000..46a700664d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/asrl-negative-shift.c
@@ -0,0 +1,30 @@
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Check that calling asrl with a negative shift amount is not interpreted as
+   undefined behavior, and that we actually use the asrl instruction.  */
+#include "arm_mve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+**foo:
+**     ...
+**     asrl    (?:ip|fp|r[0-9]+), (?:ip|fp|r[0-9]+), (?:ip|fp|r[0-9]+)(?:      
@.*|)
+**     ...
+*/
+int64_t
+foo (int64_t value, int32_t shift)
+{
+  return asrl (value, -10);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/* { dg-final { scan-assembler-not "__ARM_undef" } } */
-- 
2.34.1

Reply via email to