public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-5955] aarch64: Add LS64 extension and intrinsics
@ 2021-12-14 14:54 Przemyslaw Wirkus
  0 siblings, 0 replies; only message in thread
From: Przemyslaw Wirkus @ 2021-12-14 14:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fdcddba8f29ea3878851b8b4cd37d0fd3476d3bf

commit r12-5955-gfdcddba8f29ea3878851b8b4cd37d0fd3476d3bf
Author: Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
Date:   Tue Dec 14 14:03:38 2021 +0000

    aarch64: Add LS64 extension and intrinsics
    
    This patch is adding support for LS64 (Armv8.7-A Load/Store 64 Byte extension)
    which is part of Armv8.7-A architecture. Changes include missing plumbing for
    TARGET_LS64, LS64 data structure and intrinsics defined in ACLE. Machine
    description of intrinsics is using new V8DI mode added in a separate patch.
    __ARM_FEATURE_LS64 is defined if the Armv8.7-A LS64 instructions for atomic
    64-byte access to device memory are supported.
    
    New compiler internal type is added wrapping ACLE struct data512_t:
    
    typedef struct {
      uint64_t val[8];
    } __arm_data512_t;
    
    gcc/ChangeLog:
    
            * config/aarch64/aarch64-builtins.c (enum aarch64_builtins):
            Define AARCH64_LS64_BUILTIN_LD64B, AARCH64_LS64_BUILTIN_ST64B,
            AARCH64_LS64_BUILTIN_ST64BV, AARCH64_LS64_BUILTIN_ST64BV0.
            (aarch64_init_ls64_builtin_decl): Helper function.
            (aarch64_init_ls64_builtins): Helper function.
            (aarch64_init_ls64_builtins_types): Helper function.
            (aarch64_general_init_builtins): Init LS64 intrisics for
            TARGET_LS64.
            (aarch64_expand_builtin_ls64): LS64 intrinsics expander.
            (aarch64_general_expand_builtin): Handle aarch64_expand_builtin_ls64.
            (ls64_builtins_data): New helper struct.
            (v8di_UP): New define.
            * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define
            __ARM_FEATURE_LS64.
            * config/aarch64/aarch64.c (aarch64_classify_address): Enforce the
            V8DI range (7-bit signed scaled) for both ends of the range.
            * config/aarch64/aarch64-simd.md (movv8di): New pattern.
            (aarch64_movv8di): New pattern.
            * config/aarch64/aarch64.h (AARCH64_ISA_LS64): New define.
            (TARGET_LS64): New define.
            * config/aarch64/aarch64.md: Add UNSPEC_LD64B, UNSPEC_ST64B,
            UNSPEC_ST64BV and UNSPEC_ST64BV0.
            (ld64b): New define_insn.
            (st64b): New define_insn.
            (st64bv): New define_insn.
            (st64bv0): New define_insn.
            * config/aarch64/arm_acle.h (data512_t): New type derived from
            __arm_data512_t.
            (__arm_data512_t): New internal type.
            (__arm_ld64b): New intrinsic.
            (__arm_st64b): New intrinsic.
            (__arm_st64bv): New intrinsic.
            (__arm_st64bv0): New intrinsic.
            * config/arm/types.md: Add new type ls64.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/acle/ls64_asm.c: New test.
            * gcc.target/aarch64/acle/ls64_ld64b.c: New test.
            * gcc.target/aarch64/acle/ls64_ld64b-2.c: New test.
            * gcc.target/aarch64/acle/ls64_ld64b-3.c: New test.
            * gcc.target/aarch64/acle/ls64_st64b.c: New test.
            * gcc.target/aarch64/acle/ls64_ld_st_o0.c: New test.
            * gcc.target/aarch64/acle/ls64_st64b-2.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv-2.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv-3.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv0.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv0-2.c: New test.
            * gcc.target/aarch64/acle/ls64_st64bv0-3.c: New test.
            * gcc.target/aarch64/pragma_cpp_predefs_2.c: Add checks
            for __ARM_FEATURE_LS64.

Diff:
---
 gcc/config/aarch64/aarch64-builtins.c              | 130 +++++++++++++++++++++
 gcc/config/aarch64/aarch64-c.c                     |   2 +
 gcc/config/aarch64/aarch64-simd.md                 |  48 ++++++++
 gcc/config/aarch64/aarch64.c                       |   4 +
 gcc/config/aarch64/aarch64.h                       |   4 +
 gcc/config/aarch64/aarch64.md                      |  52 +++++++++
 gcc/config/aarch64/arm_acle.h                      |  37 ++++++
 gcc/config/arm/types.md                            |   1 +
 gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c   |  58 +++++++++
 .../gcc.target/aarch64/acle/ls64_ld64b-2.c         |  15 +++
 .../gcc.target/aarch64/acle/ls64_ld64b-3.c         |  15 +++
 gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c |  15 +++
 .../gcc.target/aarch64/acle/ls64_ld_st_o0.c        |  30 +++++
 .../gcc.target/aarch64/acle/ls64_st64b-2.c         |  15 +++
 gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv-2.c        |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv-3.c        |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv.c          |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv0-2.c       |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv0-3.c       |  15 +++
 .../gcc.target/aarch64/acle/ls64_st64bv0.c         |  15 +++
 .../gcc.target/aarch64/pragma_cpp_predefs_2.c      |  14 +++
 22 files changed, 545 insertions(+)

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 303e1e54282..0d09fe9dd6d 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -49,6 +49,7 @@
 #include "gimple-fold.h"
 
 #define v8qi_UP  E_V8QImode
+#define v8di_UP  E_V8DImode
 #define v4hi_UP  E_V4HImode
 #define v4hf_UP  E_V4HFmode
 #define v2si_UP  E_V2SImode
@@ -607,6 +608,11 @@ enum aarch64_builtins
   AARCH64_MEMTAG_BUILTIN_SET_TAG,
   AARCH64_MEMTAG_BUILTIN_GET_TAG,
   AARCH64_MEMTAG_BUILTIN_END,
+  /* LS64 builtins.  */
+  AARCH64_LS64_BUILTIN_LD64B,
+  AARCH64_LS64_BUILTIN_ST64B,
+  AARCH64_LS64_BUILTIN_ST64BV,
+  AARCH64_LS64_BUILTIN_ST64BV0,
   AARCH64_BUILTIN_MAX
 };
 
@@ -1571,6 +1577,70 @@ aarch64_init_memtag_builtins (void)
 #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
 }
 
+/* Add builtins for Load/store 64 Byte instructions.  */
+
+typedef struct
+{
+  const char *name;
+  unsigned int code;
+  tree type;
+} ls64_builtins_data;
+
+static GTY(()) tree ls64_arm_data_t = NULL_TREE;
+
+static void
+aarch64_init_ls64_builtins_types (void)
+{
+  /* Synthesize:
+
+     typedef struct {
+       uint64_t val[8];
+     } __arm_data512_t;  */
+  const char *tuple_type_name = "__arm_data512_t";
+  tree node_type = get_typenode_from_name (UINT64_TYPE);
+  tree array_type = build_array_type_nelts (node_type, 8);
+  SET_TYPE_MODE (array_type, V8DImode);
+
+  gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type));
+  gcc_assert (TYPE_ALIGN (array_type) == 64);
+
+  tree field = build_decl (input_location, FIELD_DECL,
+                           get_identifier ("val"), array_type);
+
+  ls64_arm_data_t = lang_hooks.types.simulate_record_decl (input_location,
+                         tuple_type_name,
+                         make_array_slice (&field, 1));
+
+  gcc_assert (TYPE_MODE (ls64_arm_data_t) == V8DImode);
+  gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t));
+  gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == 64);
+}
+
+static void
+aarch64_init_ls64_builtins (void)
+{
+  aarch64_init_ls64_builtins_types ();
+
+  ls64_builtins_data data[4] = {
+    {"__builtin_aarch64_ld64b", AARCH64_LS64_BUILTIN_LD64B,
+     build_function_type_list (ls64_arm_data_t,
+                               const_ptr_type_node, NULL_TREE)},
+    {"__builtin_aarch64_st64b", AARCH64_LS64_BUILTIN_ST64B,
+     build_function_type_list (void_type_node, ptr_type_node,
+                               ls64_arm_data_t, NULL_TREE)},
+    {"__builtin_aarch64_st64bv", AARCH64_LS64_BUILTIN_ST64BV,
+     build_function_type_list (uint64_type_node, ptr_type_node,
+                               ls64_arm_data_t, NULL_TREE)},
+    {"__builtin_aarch64_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0,
+     build_function_type_list (uint64_type_node, ptr_type_node,
+                               ls64_arm_data_t, NULL_TREE)},
+  };
+
+  for (size_t i = 0; i < ARRAY_SIZE (data); ++i)
+    aarch64_builtin_decls[data[i].code]
+      = aarch64_general_add_builtin (data[i].name, data[i].type, data[i].code);
+}
+
 /* Initialize fpsr fpcr getters and setters.  */
 
 static void
@@ -1660,6 +1730,9 @@ aarch64_general_init_builtins (void)
 
   if (TARGET_MEMTAG)
     aarch64_init_memtag_builtins ();
+
+  if (TARGET_LS64)
+    aarch64_init_ls64_builtins ();
 }
 
 /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group.  */
@@ -2130,6 +2203,57 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
     return target;
 }
 
+/* Function to expand an expression EXP which calls one of the Load/Store
+   64 Byte extension (LS64) builtins FCODE with the result going to TARGET.  */
+static rtx
+aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target)
+{
+  expand_operand ops[3];
+
+  switch (fcode)
+    {
+    case AARCH64_LS64_BUILTIN_LD64B:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        create_output_operand (&ops[0], target, V8DImode);
+        create_input_operand (&ops[1], op0, DImode);
+        expand_insn (CODE_FOR_ld64b, 2, ops);
+        return ops[0].value;
+      }
+    case AARCH64_LS64_BUILTIN_ST64B:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        create_output_operand (&ops[0], op0, DImode);
+        create_input_operand (&ops[1], op1, V8DImode);
+        expand_insn (CODE_FOR_st64b, 2, ops);
+        return const0_rtx;
+      }
+    case AARCH64_LS64_BUILTIN_ST64BV:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        create_output_operand (&ops[0], target, DImode);
+        create_input_operand (&ops[1], op0, DImode);
+        create_input_operand (&ops[2], op1, V8DImode);
+        expand_insn (CODE_FOR_st64bv, 3, ops);
+        return ops[0].value;
+      }
+    case AARCH64_LS64_BUILTIN_ST64BV0:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        create_output_operand (&ops[0], target, DImode);
+        create_input_operand (&ops[1], op0, DImode);
+        create_input_operand (&ops[2], op1, V8DImode);
+        expand_insn (CODE_FOR_st64bv0, 3, ops);
+        return ops[0].value;
+      }
+    }
+
+  gcc_unreachable ();
+}
+
 /* Expand a random number builtin EXP with code FCODE, putting the result
    int TARGET.  If IGNORE is true the return value is ignored.  */
 
@@ -2388,6 +2512,12 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
       || fcode == AARCH64_TME_BUILTIN_TCANCEL)
     return aarch64_expand_builtin_tme (fcode, exp, target);
 
+  if (fcode == AARCH64_LS64_BUILTIN_LD64B
+      || fcode == AARCH64_LS64_BUILTIN_ST64B
+      || fcode == AARCH64_LS64_BUILTIN_ST64BV
+      || fcode == AARCH64_LS64_BUILTIN_ST64BV0)
+    return aarch64_expand_builtin_ls64 (fcode, exp, target);
+
   if (fcode >= AARCH64_MEMTAG_BUILTIN_START
       && fcode <= AARCH64_MEMTAG_BUILTIN_END)
     return aarch64_expand_builtin_memtag (fcode, exp, target);
diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index d6653e474de..3af3e5c96da 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -200,6 +200,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 			"__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile);
   aarch64_def_or_undef (TARGET_BF16_FP,
 			"__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile);
+  aarch64_def_or_undef (TARGET_LS64,
+			"__ARM_FEATURE_LS64", pfile);
 
   /* Not for ACLE, but required to keep "float.h" correct if we switch
      target between implementations that do or do not support ARMv8.2-A
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 175a9f07e25..9ebf795a624 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -7123,6 +7123,15 @@
     }
 })
 
+(define_expand "movv8di"
+  [(set (match_operand:V8DI 0 "nonimmediate_operand")
+	(match_operand:V8DI 1 "general_operand"))]
+  "TARGET_SIMD"
+{
+  if (can_create_pseudo_p () && MEM_P (operands[0]))
+    operands[1] = force_reg (V8DImode, operands[1]);
+})
+
 (define_expand "aarch64_ld1x3<vstruct_elt>"
   [(match_operand:VSTRUCT_3QD 0 "register_operand")
    (match_operand:DI 1 "register_operand")]
@@ -7253,6 +7262,17 @@
    (set_attr "length" "<insn_count>,4,4")]
 )
 
+(define_insn "*aarch64_movv8di"
+  [(set (match_operand:V8DI 0 "nonimmediate_operand" "=r,m,r")
+	(match_operand:V8DI 1 "general_operand" " r,r,m"))]
+  "!BYTES_BIG_ENDIAN
+   && (register_operand (operands[0], V8DImode)
+       || register_operand (operands[1], V8DImode))"
+  "#"
+  [(set_attr "type" "multiple,multiple,multiple")
+   (set_attr "length" "32,16,16")]
+)
+
 (define_insn "aarch64_be_ld1<mode>"
   [(set (match_operand:VALLDI_F16 0	"register_operand" "=w")
 	(unspec:VALLDI_F16 [(match_operand:VALLDI_F16 1
@@ -7496,6 +7516,34 @@
     FAIL;
 })
 
+(define_split
+  [(set (match_operand:V8DI 0 "nonimmediate_operand")
+        (match_operand:V8DI 1 "general_operand"))]
+  "TARGET_SIMD && reload_completed"
+  [(const_int 0)]
+{
+  if (register_operand (operands[0], V8DImode)
+      && register_operand (operands[1], V8DImode))
+    {
+      aarch64_simd_emit_reg_reg_move (operands, DImode, 8);
+      DONE;
+    }
+  else if ((register_operand (operands[0], V8DImode)
+            && memory_operand (operands[1], V8DImode))
+           || (memory_operand (operands[0], V8DImode)
+            && register_operand (operands[1], V8DImode)))
+    {
+      for (int offset = 0; offset < 64; offset += 16)
+        emit_move_insn (simplify_gen_subreg (TImode, operands[0],
+                                             V8DImode, offset),
+                        simplify_gen_subreg (TImode, operands[1],
+                                             V8DImode, offset));
+      DONE;
+    }
+  else
+    FAIL;
+})
+
 (define_expand "aarch64_ld<nregs>r<vstruct_elt>"
   [(match_operand:VSTRUCT_QD 0 "register_operand")
    (match_operand:DI 1 "register_operand")]
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index d11a40c02cd..f07330cff4f 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10016,6 +10016,10 @@ aarch64_classify_address (struct aarch64_address_info *info,
 		    && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
 			|| offset_12bit_unsigned_scaled_p (mode, offset)));
 
+	  if (mode == V8DImode)
+	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
+	            && aarch64_offset_7bit_signed_scaled_p (DImode, offset + 48));
+
 	  /* A 7bit offset check because OImode will emit a ldp/stp
 	     instruction (only big endian will get here).
 	     For ldp/stp instructions, the offset is scaled for the size of a
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 5a590aaa3fb..fb2d2eda880 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -319,6 +319,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_PAUTH	   (aarch64_isa_flags & AARCH64_FL_PAUTH)
 #define AARCH64_ISA_V9		   (aarch64_isa_flags & AARCH64_FL_V9)
 #define AARCH64_ISA_MOPS	   (aarch64_isa_flags & AARCH64_FL_MOPS)
+#define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -413,6 +414,9 @@ extern unsigned aarch64_architecture_version;
 /* MOPS instructions are enabled through +mops.  */
 #define TARGET_MOPS (AARCH64_ISA_MOPS)
 
+/* LS64 instructions are enabled through +ls64.  */
+#define TARGET_LS64 (AARCH64_ISA_LS64)
+
 /* Make sure this is always defined so we don't have to check for ifdefs
    but rather use normal ifs.  */
 #ifndef TARGET_FIX_ERR_A53_835769_DEFAULT
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 9e50a26e6f4..dcdffc89e50 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -188,6 +188,12 @@
     UNSPEC_LD2_LANE
     UNSPEC_LD3_LANE
     UNSPEC_LD4_LANE
+    UNSPEC_LD64B
+    UNSPEC_ST64B
+    UNSPEC_ST64BV
+    UNSPEC_ST64BV_RET
+    UNSPEC_ST64BV0
+    UNSPEC_ST64BV0_RET
     UNSPEC_MB
     UNSPEC_MOVMEM
     UNSPEC_NOP
@@ -7571,6 +7577,52 @@
   [(set_attr "type" "memtag")]
 )
 
+;; Load/Store 64-bit (LS64) instructions.
+(define_insn "ld64b"
+  [(set (match_operand:V8DI 0 "register_operand" "=r")
+        (unspec_volatile:V8DI
+          [(mem:V8DI (match_operand:DI 1 "register_operand" "r"))]
+            UNSPEC_LD64B)
+  )]
+  "TARGET_LS64"
+  "ld64b\\t%0, [%1]"
+  [(set_attr "type" "ls64")]
+)
+
+(define_insn "st64b"
+  [(set (mem:V8DI (match_operand:DI 0 "register_operand" "=r"))
+        (unspec_volatile:V8DI [(match_operand:V8DI 1 "register_operand" "r")]
+            UNSPEC_ST64B)
+  )]
+  "TARGET_LS64"
+  "st64b\\t%1, [%0]"
+  [(set_attr "type" "ls64")]
+)
+
+(define_insn "st64bv"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV_RET))
+   (set (mem:V8DI (match_operand:DI 1 "register_operand" "r"))
+        (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")]
+            UNSPEC_ST64BV)
+  )]
+  "TARGET_LS64"
+  "st64bv\\t%0, %2, [%1]"
+  [(set_attr "type" "ls64")]
+)
+
+(define_insn "st64bv0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV0_RET))
+   (set (mem:V8DI (match_operand:DI 1 "register_operand" "r"))
+        (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")]
+            UNSPEC_ST64BV0)
+  )]
+  "TARGET_LS64"
+  "st64bv0\\t%0, %2, [%1]"
+  [(set_attr "type" "ls64")]
+)
+
 ;; AdvSIMD Stuff
 (include "aarch64-simd.md")
 
diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h
index 13f23632474..030e343490f 100644
--- a/gcc/config/aarch64/arm_acle.h
+++ b/gcc/config/aarch64/arm_acle.h
@@ -214,6 +214,43 @@ __ttest (void)
 #pragma GCC pop_options
 #endif
 
+#ifdef __ARM_FEATURE_LS64
+#pragma GCC push_options
+#pragma GCC target ("+nothing+ls64")
+
+typedef __arm_data512_t data512_t;
+
+__extension__ extern __inline data512_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_ld64b (const void *__addr)
+{
+  return __builtin_aarch64_ld64b (__addr);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64b (void *__addr, data512_t __value)
+{
+  __builtin_aarch64_st64b (__addr, __value);
+}
+
+__extension__ extern __inline uint64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64bv (void *__addr, data512_t __value)
+{
+  return __builtin_aarch64_st64bv (__addr, __value);
+}
+
+__extension__ extern __inline uint64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64bv0 (void *__addr, data512_t __value)
+{
+  return __builtin_aarch64_st64bv0 (__addr, __value);
+}
+
+#pragma GCC pop_options
+#endif
+
 #pragma GCC push_options
 #pragma GCC target ("+nothing+rng")
 __extension__ extern __inline int
diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
index b9514dafb86..6dce71fd27e 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -1122,6 +1122,7 @@
   coproc,\
   tme,\
   memtag,\
+  ls64,\
   mve_move,\
   mve_store,\
   mve_load"
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c
new file mode 100644
index 00000000000..ba9960c9a3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+/* Inline assembly for LS64 instructions.  */
+
+#include <arm_acle.h>
+
+void
+ls64_load (data512_t *output, const void *addr)
+{
+    __asm__ volatile ("ld64b %0, [%1]"
+                      : "=r" (*output)
+                      : "r" (addr)
+                      : "memory");
+}
+
+/* { dg-final { scan-assembler-times {ld64b } 1 } } */
+
+void
+ls64_store (const data512_t *input, void *addr)
+{
+    __asm__ volatile ("st64b %1, [%0]"
+                      : /* No outputs.  */
+                      : "r" (addr), "r" (*input)
+                      : "memory");
+}
+
+/* { dg-final { scan-assembler-times {st64b } 1 } } */
+
+uint64_t
+ls64_store_v (const data512_t *input, void *addr)
+{
+    uint64_t status;
+    __asm__ volatile ("st64bv %0, %2, [%1]"
+                      : "=r" (status)
+                      : "r" (addr), "r" (*input)
+                      : "memory");
+    return status;
+}
+
+/* { dg-final { scan-assembler-times {st64bv } 1 } } */
+
+uint64_t
+ls64_store_v0 (const data512_t *input, void *addr)
+{
+    uint64_t status;
+    __asm__ volatile ("st64bv0 %0, %2, [%1]"
+                      : "=r" (status)
+                      : "r" (addr), "r" (*input)
+                      : "memory");
+    return status;
+}
+
+/* { dg-final { scan-assembler-times {st64bv0 } 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c
new file mode 100644
index 00000000000..2a94657a31a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func (const void * addr) {
+    data512_t ret = __arm_ld64b (addr);
+}
+
+/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c
new file mode 100644
index 00000000000..155ea401f23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(const void * addr, data512_t *data) {
+  *data = __arm_ld64b (addr);
+}
+
+/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c
new file mode 100644
index 00000000000..e3fc1411221
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+data512_t
+func(const void * addr) {
+  return __arm_ld64b (addr);
+}
+
+/* { dg-final { scan-assembler-times {ld64b\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c
new file mode 100644
index 00000000000..550d75c8e0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld_st_o0.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O0" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+/* Make sure no issues when compile with -O0.  */
+
+data512_t
+func1 (const void * addr) {
+  return __arm_ld64b (addr);
+}
+
+void
+func2 (void *addr, data512_t value) {
+    __arm_st64b (addr, value);
+}
+
+uint64_t
+func3 (void *addr, data512_t value) {
+    return  __arm_st64bv (addr, value);
+}
+
+uint64_t
+func4 (void *addr, data512_t value) {
+    return __arm_st64bv0 (addr, value);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c
new file mode 100644
index 00000000000..bfd737b86c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t *value) {
+    __arm_st64b (addr, *value);
+}
+
+/* { dg-final { scan-assembler-times {st64b\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c
new file mode 100644
index 00000000000..75b91803eef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t value) {
+    __arm_st64b (addr, value);
+}
+
+/* { dg-final { scan-assembler-times {st64b\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c
new file mode 100644
index 00000000000..c3ef83e57eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t value) {
+    __arm_st64bv (addr, value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c
new file mode 100644
index 00000000000..370db7960ec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t *value) {
+    __arm_st64bv (addr, *value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c
new file mode 100644
index 00000000000..52ef9c45931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+uint64_t
+func(void *addr, data512_t value) {
+    return  __arm_st64bv (addr, value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c
new file mode 100644
index 00000000000..c49fa56d940
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t value) {
+    __arm_st64bv0 (addr, value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c
new file mode 100644
index 00000000000..af6917c795f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+void
+func(void *addr, data512_t *value) {
+    __arm_st64bv0 (addr, *value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c
new file mode 100644
index 00000000000..bce10ae3653
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+ls64 -O2" } */
+
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+
+#include <arm_acle.h>
+
+uint64_t
+func(void *addr, data512_t value) {
+    return __arm_st64bv0 (addr, value);
+}
+
+/* { dg-final { scan-assembler-times {st64bv0\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c
index 7244359ccfb..2d76bfc23df 100644
--- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c
@@ -240,6 +240,20 @@
 #endif
 #pragma GCC pop_options
 
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8.7-a")
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8.7-a+ls64")
+#ifndef __ARM_FEATURE_LS64
+#error "__ARM_FEATURE_LS64 is not defined but should be!"
+#endif
+#pragma GCC pop_options
+
 #pragma GCC pop_options
 
 int


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-12-14 14:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-14 14:54 [gcc r12-5955] aarch64: Add LS64 extension and intrinsics Przemyslaw Wirkus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).