diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 5053bf0f8fd6638bf84a6df06c0987a0216b69e7..d4a82eec3b26bfd1cb976d0870d60ee7d10b689a 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
@@ -615,6 +616,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
 };
 
@@ -1579,6 +1585,71 @@ 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 void
+aarch64_init_ls64_builtin_decl (const char *name, tree type, unsigned int code)
+{
+  aarch64_builtin_decls[code] = aarch64_general_add_builtin (name, type, code);
+}
+
+static GTY(()) tree ls64_arm_data_t = NULL_TREE;
+
+static void
+aarch64_init_ls64_builtins_types (void)
+{
+  /* Synthesize the name of the user-visible vector tuple type.  */
+  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);
+  unsigned int alignment = known_eq (GET_MODE_SIZE (E_V8DImode), 64) ? 64 : 0;
+
+  gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type));
+  gcc_assert (TYPE_ALIGN (array_type) == alignment);
+
+  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_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t));
+  gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == alignment);
+}
+
+static void
+aarch64_init_ls64_builtins (void)
+{
+  ls64_builtins_data data[4] = {
+    {"__builtin_aarch64_ld64b", AARCH64_LS64_BUILTIN_LD64B,
+     build_function_type_list (aarch64_simd_intXI_type_node,
+                               const_ptr_type_node, NULL_TREE)},
+    {"__builtin_aarch64_st64b", AARCH64_LS64_BUILTIN_ST64B,
+     build_function_type_list (void_type_node, ptr_type_node,
+                               aarch64_simd_intXI_type_node, NULL_TREE)},
+    {"__builtin_aarch64_st64bv", AARCH64_LS64_BUILTIN_ST64BV,
+     build_function_type_list (uint64_type_node, ptr_type_node,
+                               aarch64_simd_intXI_type_node, NULL_TREE)},
+    {"__builtin_aarch64_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0,
+     build_function_type_list (uint64_type_node, ptr_type_node,
+                               aarch64_simd_intXI_type_node, NULL_TREE)},
+  };
+
+  for (size_t i = 0; i < ARRAY_SIZE (data); ++i)
+    aarch64_init_ls64_builtin_decl (data[i].name, data[i].type, data[i].code);
+
+  aarch64_init_ls64_builtins_types ();
+}
+
 /* Initialize fpsr fpcr getters and setters.  */
 
 static void
@@ -1668,6 +1739,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.  */
@@ -2138,6 +2212,60 @@ 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.
+   If IGNORE is true the return value is ignored.  */
+static rtx
+aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target, int ignore)
+{
+  switch (fcode)
+    {
+    case AARCH64_LS64_BUILTIN_LD64B:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        op0 = force_reg (Pmode, op0);
+        /* Do not emit instruction when return value is ignored.  */
+        if (ignore)
+          return target;
+        target = convert_to_mode (V8DImode, target, true);
+        emit_insn (GEN_FCN (CODE_FOR_ld64b) (target, op0));
+        break;
+      }
+    case AARCH64_LS64_BUILTIN_ST64B:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        op0 = force_reg (Pmode, op0);
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        op1 = convert_to_mode (V8DImode, op1, true);
+        emit_insn (GEN_FCN (CODE_FOR_st64b) (op0, op1));
+        break;
+      }
+    case AARCH64_LS64_BUILTIN_ST64BV:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        op0 = force_reg (Pmode, op0);
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        op1 = convert_to_mode (V8DImode, op1, true);
+        target = ignore ? gen_reg_rtx(DImode) : force_reg (DImode, target);
+        emit_insn (GEN_FCN (CODE_FOR_st64bv) (target, op0, op1));
+        break;
+      }
+    case AARCH64_LS64_BUILTIN_ST64BV0:
+      {
+        rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+        op0 = force_reg (Pmode, op0);
+        rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
+        op1 = convert_to_mode (V8DImode, op1, true);
+        target = ignore ? gen_reg_rtx(DImode) : force_reg (DImode, target);
+        emit_insn (GEN_FCN (CODE_FOR_st64bv0) (target, op0, op1));
+        break;
+      }
+    default :
+      gcc_unreachable ();
+    }
+    return target;
+}
+
 /* Expand a random number builtin EXP with code FCODE, putting the result
    int TARGET.  If IGNORE is true the return value is ignored.  */
 
@@ -2396,6 +2524,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, ignore);
+
   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 d6653e474dec9bcddde2106f36ceb22f1d43375c..3af3e5c96daf674648dbc008b15ade0e303b66f8 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.h b/gcc/config/aarch64/aarch64.h
index 2792bb29adbbb5b3145b3f767615af8edbc30b08..426ad5ac77376f561c92d3e35b627939eb481773 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -310,6 +310,8 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_V8_R	   (aarch64_isa_flags & AARCH64_FL_V8_R)
 #define AARCH64_ISA_PAUTH	   (aarch64_isa_flags & AARCH64_FL_PAUTH)
 #define AARCH64_ISA_V9		   (aarch64_isa_flags & AARCH64_FL_V9)
+#define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+#define AARCH64_ISA_V8_7	   (aarch64_isa_flags & AARCH64_FL_V8_7)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -401,6 +403,9 @@ extern unsigned aarch64_architecture_version;
 /* PAUTH instructions are enabled through +pauth.  */
 #define TARGET_PAUTH (AARCH64_ISA_PAUTH)
 
+/* 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 4035e061706793849c68ae09bcb2e4b9580ab7b6..bf4a23c8682767ae706ba3879938aed08f394cc2 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -187,6 +187,10 @@ (define_c_enum "unspec" [
     UNSPEC_LD2_LANE
     UNSPEC_LD3_LANE
     UNSPEC_LD4_LANE
+    UNSPEC_LD64B
+    UNSPEC_ST64B
+    UNSPEC_ST64BV
+    UNSPEC_ST64BV0
     UNSPEC_MB
     UNSPEC_NOP
     UNSPEC_PACIA1716
@@ -7499,6 +7503,45 @@ (define_insn "stg"
   [(set_attr "type" "memtag")]
 )
 
+;; Load/Store 64-bit (LS64) instructions.
+(define_insn "ld64b"
+  [(set (match_operand:V8DI 0 "register_operand" "=r")
+        (unspec: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:V8DI [(match_operand:V8DI 1 "register_operand" "r")] UNSPEC_ST64B)
+  )]
+  "TARGET_LS64"
+  "st64b\\t%1, [%0]"
+  [(set_attr "type" "ls64")]
+)
+
+(define_insn "st64bv"
+  [(clobber (match_operand:DI 0 "register_operand" "=r"))
+   (set (mem:V8DI (match_operand:DI 1 "register_operand" "=r"))
+        (unspec:V8DI [(match_operand:V8DI 2 "register_operand" "r")] UNSPEC_ST64BV)
+  )]
+  "TARGET_LS64"
+  "st64bv\\t%0, %2, [%1]"
+  [(set_attr "type" "ls64")]
+)
+
+(define_insn "st64bv0"
+  [(clobber (match_operand:DI 0 "register_operand" "=r"))
+   (set (mem:V8DI (match_operand:DI 1 "register_operand" "=r"))
+        (unspec: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 13f23632474b260122f30a3c566033664b0b5963..26d886949a34f77a65f55fbf3b4cc01884bfd883 100644
--- a/gcc/config/aarch64/arm_acle.h
+++ b/gcc/config/aarch64/arm_acle.h
@@ -214,6 +214,57 @@ __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)
+{
+  __builtin_aarch64_simd_xi __o;
+  data512_t __temp = { };
+  __o = __builtin_aarch64_ld64b (addr);
+  __builtin_memcpy (&__temp, &__o, sizeof (__o));
+  return __temp;
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64b (void *addr, data512_t value)
+{
+  __builtin_aarch64_simd_xi __o;
+  __builtin_memcpy (&__o, &value, sizeof (__o));
+  __builtin_aarch64_st64b (addr, __o);
+}
+
+__extension__ extern __inline uint64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64bv (void *addr, data512_t value)
+{
+  uint64_t __ret;
+  __builtin_aarch64_simd_xi __o;
+  __builtin_memcpy (&__o, &value, sizeof (__o));
+  __ret = __builtin_aarch64_st64bv (addr, __o);
+  return __ret;
+}
+
+__extension__ extern __inline uint64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+__arm_st64bv0 (void *addr, data512_t value)
+{
+  uint64_t __ret;
+  __builtin_aarch64_simd_xi __o;
+  __builtin_memcpy (&__o, &value, sizeof (__o));
+  __ret = __builtin_aarch64_st64bv0 (addr, __o);
+  return __ret;
+}
+
+#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 b9514dafb86a280bee3d3f84845e0743cd18a34d..6dce71fd27e5dfbd08746509bc6fdeeade69a4a4 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -1122,6 +1122,7 @@ (define_attr "type"
   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 0000000000000000000000000000000000000000..60738a5b8d6b35837a7b286d16416a0eb289e34e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_asm.c
@@ -0,0 +1,130 @@
+/* { 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 x[0-9]+, \[x[0-9]+\]} 1 } } */
+
+/* LD64B <Xt>, [<Xn>] - make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {ld64b x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {ld64b x9, \[x9\]} } } */
+
+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 x[0-9]+, \[x[0-9]+\]} 1 } } */
+
+/* ST64B <Xt>, [<Xn>] - make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64b x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64b x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64b x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64b x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64b x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64b x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64b x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64b x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64b x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64b x9, \[x9\]} } } */
+
+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 x[0-9]+, x[0-9]+, \[x[0-9]+\]} 1 } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv x0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv x1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv x2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv x3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv x4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv x5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv x6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv x7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv x8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv x9, x9,} } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv x[0-9]+, x9, \[x9\]} } } */
+
+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 x[0-9]+, x[0-9]+, \[x[0-9]+\]} 1 } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv0 x0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x9, x9,} } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0 x[0-9]+, x9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..1d39618b44367522d8a29b77f2a79e339ceb35b5
--- /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);   /* Should be optimized out.  */
+}
+
+/* { dg-final { scan-assembler-not {ld64b\tx[0-9]+, \[x[0-9]+\]\n} } } */
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 0000000000000000000000000000000000000000..d8a3f6c51fb5f07137eea5b032d4fdca9b1aa93b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_ld64b.c
@@ -0,0 +1,27 @@
+/* { 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\tx[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* LD64B <Xt>, [<Xn>] - make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {ld64b\tx0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {ld64b\tx9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..757ff738ada8b706b68b517f20bec7b1ad05a5b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64b.c
@@ -0,0 +1,27 @@
+/* { 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\tx[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* ST64B <Xt>, [<Xn>] - make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64b\tx0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64b\tx9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..3fb2520223c294dcd80548bad1d0c176a696c37b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv-2.c
@@ -0,0 +1,39 @@
+/* { 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\tx[0-9]+, x[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv\tx0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx9, x9,} } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..7bb40c3a9db643a5b2548e4e7e639224126e03f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv.c
@@ -0,0 +1,39 @@
+/* { 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\tx[0-9]+, x[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv\tx0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx9, x9,} } } */
+
+/* ST64BV <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv\tx[0-9]+, x9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..bd8fd5dcf41d3b0e9dab6be53cc099014cdcf1e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0-2.c
@@ -0,0 +1,39 @@
+/* { 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\tx[0-9]+, x[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv0\tx0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx9, x9,} } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x9, \[x9\]} } } */
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 0000000000000000000000000000000000000000..7a8e9bf53ad0f03a382a950783949989182adcf9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/ls64_st64bv0.c
@@ -0,0 +1,39 @@
+/* { 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\tx[0-9]+, x[0-9]+, \[x[0-9]+\]\n} 1 } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xs != Xt  */
+/* { dg-final { scan-assembler-not {st64bv0\tx0, x0,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx1, x1,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx2, x2,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx3, x3,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx4, x4,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx5, x5,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx6, x6,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx7, x7,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx8, x8,} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx9, x9,} } } */
+
+/* ST64BV0 <Xs>, <Xt>, [<Xn>]  -  make sure Xt != Xn  */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x0, \[x0\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x1, \[x1\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x2, \[x2\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x3, \[x3\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x4, \[x4\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x5, \[x5\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x6, \[x6\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x7, \[x7\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x8, \[x8\]} } } */
+/* { dg-final { scan-assembler-not {st64bv0\tx[0-9]+, x9, \[x9\]} } } */
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 7244359ccfb9cbcbbd8285b050113c004a6af2a6..2d76bfc23dfdcd78a74ec0e4845a3bd8d110b010 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
