[clang] [llvm] [AArch64] Split FeatureLS64 to LS64_ACCDATA and LS64_V. (PR #101712)

Alexandros Lamprineas via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 18 03:31:09 PDT 2024


https://github.com/labrinea updated https://github.com/llvm/llvm-project/pull/101712

>From 2fe8ef63846989952a1c72b83114aabe6f36637a Mon Sep 17 00:00:00 2001
From: Alexandros Lamprineas <alexandros.lamprineas at arm.com>
Date: Fri, 2 Aug 2024 17:32:23 +0100
Subject: [PATCH 1/2] [AArch64] Split FeatureLS64 to LS64_ACCDATA and LS64_V.

These extensions depend on each other as follows:
ls64 -> ls64_v -> ls64_accdata

Currently in LLVM FeatureLS64 models all three lumped together.
However the architecture does not mandate that all three need
to be implemented at the same time. Therefore it makes sense to
split them. This will allow Function Multiversioning to enable
backend features for 'ls64' and 'ls64_v' which was previously
impossible. I have added an override for the user visible name
of FeatureLS64_ACCDATA ('ls64') to preserve the old semantics
for backwards compatibility with the command line and the target
attribute.
---
 clang/lib/Basic/Targets/AArch64.cpp           |  13 +-
 clang/lib/Basic/Targets/AArch64.h             |   2 +
 clang/test/CodeGen/aarch64-fmv-dependencies.c |   8 +-
 clang/test/CodeGen/aarch64-ls64.c             |   8 +-
 clang/test/CodeGen/attr-target-version.c      | 112 +++++++++---------
 .../CodeGenCXX/attr-target-clones-aarch64.cpp |   4 +-
 .../aarch64-neoverse-v3.c                     |   4 +-
 .../aarch64-neoverse-v3ae.c                   |   4 +-
 .../print-supported-extensions-aarch64.c      |   2 +-
 clang/test/Sema/attr-target-clones-aarch64.c  |   4 +-
 llvm/lib/Target/AArch64/AArch64FMV.td         |   6 +-
 llvm/lib/Target/AArch64/AArch64Features.td    |  14 ++-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  23 ++--
 llvm/lib/Target/AArch64/AArch64Processors.td  |   4 +-
 .../Target/AArch64/AArch64SystemOperands.td   |   2 +-
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |   2 +
 llvm/test/CodeGen/AArch64/ls64-intrinsics.ll  |   4 +-
 llvm/test/MC/AArch64/armv8.7a-ls64.s          |   2 +-
 .../MC/Disassembler/AArch64/armv8.7a-ls64.txt |   2 +-
 .../TargetParser/TargetParserTest.cpp         |  69 +++++------
 20 files changed, 166 insertions(+), 123 deletions(-)

diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 6ba31cc05a0d75..b1578671d4dd5d 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -768,7 +768,9 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
       .Case("predres", HasPredRes)
       .Cases("ssbs", "ssbs2", HasSSBS)
       .Case("bti", HasBTI)
-      .Cases("ls64", "ls64_v", "ls64_accdata", HasLS64)
+      .Case("ls64", HasLS64)
+      .Case("ls64_v", HasLS64_V)
+      .Case("ls64_accdata", HasLS64_ACCDATA)
       .Case("wfxt", HasWFxT)
       .Case("rcpc3", HasRCPC3)
       .Default(false);
@@ -1045,6 +1047,15 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       HasLSE = true;
     if (Feature == "+ls64")
       HasLS64 = true;
+    if (Feature == "+ls64_v") {
+      HasLS64 = true;
+      HasLS64_V = true;
+    }
+    if (Feature == "+ls64_accdata") {
+      HasLS64 = true;
+      HasLS64_V = true;
+      HasLS64_ACCDATA = true;
+    }
     if (Feature == "+rand")
       HasRandGen = true;
     if (Feature == "+flagm")
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 7bdf5a2b4106e4..1e5d46da158006 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -45,6 +45,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
   bool HasTME = false;
   bool HasPAuth = false;
   bool HasLS64 = false;
+  bool HasLS64_V = false;
+  bool HasLS64_ACCDATA = false;
   bool HasRandGen = false;
   bool HasMatMul = false;
   bool HasBFloat16 = false;
diff --git a/clang/test/CodeGen/aarch64-fmv-dependencies.c b/clang/test/CodeGen/aarch64-fmv-dependencies.c
index e39c7adbe4a9b0..18eff4f46402db 100644
--- a/clang/test/CodeGen/aarch64-fmv-dependencies.c
+++ b/clang/test/CodeGen/aarch64-fmv-dependencies.c
@@ -66,13 +66,13 @@ __attribute__((target_version("i8mm"))) int fmv(void) { return 0; }
 // CHECK: define dso_local i32 @fmv._Mjscvt() #[[jscvt:[0-9]+]] {
 __attribute__((target_version("jscvt"))) int fmv(void) { return 0; }
 
-// CHECK: define dso_local i32 @fmv._Mls64() #[[ATTR0:[0-9]+]] {
+// CHECK: define dso_local i32 @fmv._Mls64() #[[ls64:[0-9]+]] {
 __attribute__((target_version("ls64"))) int fmv(void) { return 0; }
 
 // CHECK: define dso_local i32 @fmv._Mls64_accdata() #[[ls64_accdata:[0-9]+]] {
 __attribute__((target_version("ls64_accdata"))) int fmv(void) { return 0; }
 
-// CHECK: define dso_local i32 @fmv._Mls64_v() #[[ATTR0:[0-9]+]] {
+// CHECK: define dso_local i32 @fmv._Mls64_v() #[[ls64_v:[0-9]+]] {
 __attribute__((target_version("ls64_v"))) int fmv(void) { return 0; }
 
 // CHECK: define dso_local i32 @fmv._Mlse() #[[lse:[0-9]+]] {
@@ -210,7 +210,9 @@ int caller() {
 // CHECK: attributes #[[frintts]] = { {{.*}} "target-features"="+fp-armv8,+fptoint,+neon,+outline-atomics,+v8a"
 // CHECK: attributes #[[i8mm]] = { {{.*}} "target-features"="+fp-armv8,+i8mm,+neon,+outline-atomics,+v8a"
 // CHECK: attributes #[[jscvt]] = { {{.*}} "target-features"="+fp-armv8,+jsconv,+neon,+outline-atomics,+v8a"
-// CHECK: attributes #[[ls64_accdata]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+neon,+outline-atomics,+v8a"
+// CHECK: attributes #[[ls64]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+neon,+outline-atomics,+v8a"
+// CHECK: attributes #[[ls64_accdata]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+ls64_accdata,+ls64_v,+neon,+outline-atomics,+v8a"
+// CHECK: attributes #[[ls64_v]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+ls64_v,+neon,+outline-atomics,+v8a"
 // CHECK: attributes #[[lse]] = { {{.*}} "target-features"="+fp-armv8,+lse,+neon,+outline-atomics,+v8a"
 // CHECK: attributes #[[memtag2]] = { {{.*}} "target-features"="+fp-armv8,+mte,+neon,+outline-atomics,+v8a"
 // CHECK: attributes #[[mops]] = { {{.*}} "target-features"="+fp-armv8,+mops,+neon,+outline-atomics,+v8a"
diff --git a/clang/test/CodeGen/aarch64-ls64.c b/clang/test/CodeGen/aarch64-ls64.c
index 23894f3e399d47..d5b3a10de223ca 100644
--- a/clang/test/CodeGen/aarch64-ls64.c
+++ b/clang/test/CodeGen/aarch64-ls64.c
@@ -1,8 +1,8 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
-// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -emit-llvm -x c %s -o - | FileCheck --check-prefixes=CHECK-C %s
-// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -emit-llvm -x c++ %s -o - | FileCheck --check-prefixes=CHECK-CXX %s
-// RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -emit-llvm -x c %s -o - | FileCheck  --check-prefixes=CHECK-C %s
-// RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -emit-llvm -x c++ %s -o - | FileCheck  --check-prefixes=CHECK-CXX %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -target-feature +ls64_v -target-feature +ls64_accdata -emit-llvm -x c %s -o - | FileCheck --check-prefixes=CHECK-C %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -target-feature +ls64_v -target-feature +ls64_accdata -emit-llvm -x c++ %s -o - | FileCheck --check-prefixes=CHECK-CXX %s
+// RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -target-feature +ls64_v -target-feature +ls64_accdata -emit-llvm -x c %s -o - | FileCheck  --check-prefixes=CHECK-C %s
+// RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -target-feature +ls64_v -target-feature +ls64_accdata -emit-llvm -x c++ %s -o - | FileCheck  --check-prefixes=CHECK-CXX %s
 
 #include <arm_acle.h>
 
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index b058f84f78baad..5fa6d2b1fc6e9e 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -221,14 +221,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd
-// CHECK-SAME: () #[[ATTR5]] {
+// CHECK-SAME: () #[[ATTR10:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_one._Mdpb
-// CHECK-SAME: () #[[ATTR10:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
 //
@@ -263,7 +263,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd
-// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 4
 //
@@ -354,14 +354,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_with_forward_default_decl._Mmops
-// CHECK-SAME: () #[[ATTR13:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR14:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_extern_forward_default_decl._Mdotprod
-// CHECK-SAME: () #[[ATTR14:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR15:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -375,7 +375,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_with_default_def._Msve
-// CHECK-SAME: () #[[ATTR15:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR16:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -389,7 +389,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def._Mfp16
-// CHECK-SAME: () #[[ATTR11]] {
+// CHECK-SAME: () #[[ATTR12]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -410,14 +410,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def._Mlse
-// CHECK-SAME: () #[[ATTR16:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR17:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@unused_without_default._Mrdm
-// CHECK-SAME: () #[[ATTR17:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR18:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -431,14 +431,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mjscvt
-// CHECK-SAME: () #[[ATTR19:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR20:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mrdm
-// CHECK-SAME: () #[[ATTR17]] {
+// CHECK-SAME: () #[[ATTR18]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
 //
@@ -618,7 +618,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb
-// CHECK-SAME: () #[[ATTR20:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR22:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -660,91 +660,91 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
-// CHECK-SAME: () #[[ATTR21:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR23:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16MrdmMsme
-// CHECK-SAME: () #[[ATTR22:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR24:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf32mmMi8mmMsha3
-// CHECK-SAME: () #[[ATTR23:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR25:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 12
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MditMsve-ebf16
-// CHECK-SAME: () #[[ATTR24:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR26:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 8
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MdpbMrcpc2
-// CHECK-SAME: () #[[ATTR25:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR27:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 6
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mdpb2Mjscvt
-// CHECK-SAME: () #[[ATTR26:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR28:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 7
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfrinttsMrcpc
-// CHECK-SAME: () #[[ATTR27:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR29:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MsveMsve-bf16
-// CHECK-SAME: () #[[ATTR28:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR30:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 4
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2-aesMsve2-sha3
-// CHECK-SAME: () #[[ATTR29:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR31:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 5
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-bitpermMsve2-pmull128
-// CHECK-SAME: () #[[ATTR30:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR32:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 9
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag2Msve2-sm4
-// CHECK-SAME: () #[[ATTR31:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR33:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 10
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag3MmopsMrcpc3
-// CHECK-SAME: () #[[ATTR32:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR34:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 11
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMdotprod
-// CHECK-SAME: () #[[ATTR14]] {
+// CHECK-SAME: () #[[ATTR15]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 13
 //
@@ -758,14 +758,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfpMsm4
-// CHECK-SAME: () #[[ATTR33:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR35:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 15
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MlseMrdm
-// CHECK-SAME: () #[[ATTR34:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR36:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 16
 //
@@ -1115,39 +1115,41 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand" }
 // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64" }
 // CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+sha2" }
-// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+ls64,+neon" }
+// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+ls64,+ls64_accdata,+ls64_v,+neon" }
 // CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fp16fml,+fullfp16,+neon" }
 // CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
-// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc" }
+// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+ls64,+ls64_v" }
 // CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" }
 // CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2" }
 // CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp" }
-// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
-// CHECK: attributes #[[ATTR12:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" }
-// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" }
-// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
-// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" }
-// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" }
-// CHECK: attributes #[[ATTR18:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon" }
-// CHECK: attributes #[[ATTR19]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon" }
-// CHECK: attributes #[[ATTR20]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb" }
-// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+neon,+sve" }
-// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+neon,+rdm,+sme" }
-// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve" }
-// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+neon,+sve" }
-// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc" }
-// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+jsconv,+neon" }
-// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc" }
-// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sve" }
-// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3" }
-// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm" }
-// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4" }
-// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3" }
-// CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sm4" }
-// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+rdm" }
-// CHECK: attributes #[[ATTR35:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" }
+// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+ls64,+neon" }
+// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp" }
+// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
+// CHECK: attributes #[[ATTR13:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" }
+// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" }
+// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
+// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" }
+// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" }
+// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon" }
+// CHECK: attributes #[[ATTR20]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon" }
+// CHECK: attributes #[[ATTR21:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
+// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb" }
+// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+neon,+sve" }
+// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+neon,+rdm,+sme" }
+// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve" }
+// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+neon,+sve" }
+// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc" }
+// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+jsconv,+neon" }
+// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc" }
+// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sve" }
+// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3" }
+// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm" }
+// CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4" }
+// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3" }
+// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sm4" }
+// CHECK: attributes #[[ATTR36]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+rdm" }
+// CHECK: attributes #[[ATTR37:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" }
 //.
 // CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
 // CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
index 6405621a9d6477..21928558401aef 100644
--- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
@@ -240,8 +240,8 @@ void run_foo_tml() {
 // CHECK-NEXT:    ret ptr @_ZN7MyClassIisE7foo_tmlEv.default
 //
 //.
-// CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
-// CHECK: attributes #[[ATTR1]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
+// CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+ls64_v,+neon" }
+// CHECK: attributes #[[ATTR1]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64,+ls64_accdata,+ls64_v" }
 // CHECK: attributes #[[ATTR2]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 // CHECK: attributes #[[ATTR3]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
 // CHECK: attributes #[[ATTR4]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3.c b/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3.c
index 89aef5a47f72cb..6302a66b057f4f 100644
--- a/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3.c
+++ b/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3.c
@@ -33,7 +33,9 @@
 // CHECK-NEXT:     FEAT_LOR                                               Enable Armv8.1-A Limited Ordering Regions extension
 // CHECK-NEXT:     FEAT_LRCPC                                             Enable support for RCPC extension
 // CHECK-NEXT:     FEAT_LRCPC2                                            Enable Armv8.4-A RCPC instructions with Immediate Offsets
-// CHECK-NEXT:     FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA              Enable Armv8.7-A LD64B/ST64B Accelerator Extension
+// CHECK-NEXT:     FEAT_LS64                                              Enable single-copy atomic 64-byte loads and stores without status result
+// CHECK-NEXT:     FEAT_LS64_ACCDATA                                      Enable single-copy atomic 64-byte EL0 stores with status result
+// CHECK-NEXT:     FEAT_LS64_V                                            Enable single-copy atomic 64-byte stores with status result
 // CHECK-NEXT:     FEAT_LSE                                               Enable Armv8.1-A Large System Extension (LSE) atomic instructions
 // CHECK-NEXT:     FEAT_LSE2                                              Enable Armv8.4-A Large System Extension 2 (LSE2) atomicity rules
 // CHECK-NEXT:     FEAT_MPAM                                              Enable Armv8.4-A Memory system Partitioning and Monitoring extension
diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3ae.c b/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3ae.c
index eda46de652f6fc..27237d8d477cf3 100644
--- a/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3ae.c
+++ b/clang/test/Driver/print-enabled-extensions/aarch64-neoverse-v3ae.c
@@ -33,7 +33,9 @@
 // CHECK-NEXT:     FEAT_LOR                                               Enable Armv8.1-A Limited Ordering Regions extension
 // CHECK-NEXT:     FEAT_LRCPC                                             Enable support for RCPC extension
 // CHECK-NEXT:     FEAT_LRCPC2                                            Enable Armv8.4-A RCPC instructions with Immediate Offsets
-// CHECK-NEXT:     FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA              Enable Armv8.7-A LD64B/ST64B Accelerator Extension
+// CHECK-NEXT:     FEAT_LS64                                              Enable single-copy atomic 64-byte loads and stores without status result
+// CHECK-NEXT:     FEAT_LS64_ACCDATA                                      Enable single-copy atomic 64-byte EL0 stores with status result
+// CHECK-NEXT:     FEAT_LS64_V                                            Enable single-copy atomic 64-byte stores with status result
 // CHECK-NEXT:     FEAT_LSE                                               Enable Armv8.1-A Large System Extension (LSE) atomic instructions
 // CHECK-NEXT:     FEAT_LSE2                                              Enable Armv8.4-A Large System Extension 2 (LSE2) atomicity rules
 // CHECK-NEXT:     FEAT_MPAM                                              Enable Armv8.4-A Memory system Partitioning and Monitoring extension
diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c
index 6b969d50610f8b..72d78c16abacfd 100644
--- a/clang/test/Driver/print-supported-extensions-aarch64.c
+++ b/clang/test/Driver/print-supported-extensions-aarch64.c
@@ -33,7 +33,7 @@
 // CHECK-NEXT:     i8mm                FEAT_I8MM                                              Enable Matrix Multiply Int8 Extension
 // CHECK-NEXT:     ite                 FEAT_ITE                                               Enable Armv9.4-A Instrumentation Extension
 // CHECK-NEXT:     jscvt               FEAT_JSCVT                                             Enable Armv8.3-A JavaScript FP conversion instructions
-// CHECK-NEXT:     ls64                FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA              Enable Armv8.7-A LD64B/ST64B Accelerator Extension
+// CHECK-NEXT:     ls64                FEAT_LS64_ACCDATA                                      Enable single-copy atomic 64-byte EL0 stores with status result
 // CHECK-NEXT:     lse                 FEAT_LSE                                               Enable Armv8.1-A Large System Extension (LSE) atomic instructions
 // CHECK-NEXT:     lse128              FEAT_LSE128                                            Enable Armv9.4-A 128-bit Atomic instructions
 // CHECK-NEXT:     lut                 FEAT_LUT                                               Enable Lookup Table instructions
diff --git a/clang/test/Sema/attr-target-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c
index bc3fceab82825b..bfc08118a8ffc6 100644
--- a/clang/test/Sema/attr-target-clones-aarch64.c
+++ b/clang/test/Sema/attr-target-clones-aarch64.c
@@ -5,7 +5,7 @@ void __attribute__((target_clones("fp16+sve2-aes", "sb+sve2-sha3+rcpc3+mops", "r
 // expected-warning at +1 {{unsupported 'default' in the 'target_clones' attribute string; 'target_clones' attribute ignored}}
 void __attribute__((target_clones("default+sha3"))) warn1(void);
 // expected-warning at +1 {{version list contains entries that don't impact code generation}}
-void __attribute__((target_clones("ssbs+ls64"))) warn2(void);
+void __attribute__((target_clones("ssbs"))) warn2(void);
 
 // expected-error at +2 {{'target_clones' and 'target_version' attributes are not compatible}}
 // expected-note at +1 {{conflicting attribute is here}}
@@ -24,7 +24,7 @@ int __attribute__((target_clones("rng", "fp16fml+fp", "default"))) redecl4(void)
 // expected-error at +3 {{'target_clones' attribute does not match previous declaration}}
 // expected-note at -2 {{previous declaration is here}}
 // expected-warning at +1 {{version list contains entries that don't impact code generation}}
-int __attribute__((target_clones("dgh+memtag+rpres+ls64_v", "ebf16+dpb+sha1", "default"))) redecl4(void) { return 1; }
+int __attribute__((target_clones("dgh+memtag+rpres", "ebf16+dpb+sha1", "default"))) redecl4(void) { return 1; }
 
 int __attribute__((target_version("flagm2"))) redef2(void) { return 1; }
 // expected-error at +2 {{multiversioned function redeclarations require identical target attributes}}
diff --git a/llvm/lib/Target/AArch64/AArch64FMV.td b/llvm/lib/Target/AArch64/AArch64FMV.td
index 7a40c83b2bb21e..ed2a49c6db4f15 100644
--- a/llvm/lib/Target/AArch64/AArch64FMV.td
+++ b/llvm/lib/Target/AArch64/AArch64FMV.td
@@ -58,9 +58,9 @@ def : FMVExtension<"fp16fml", "FEAT_FP16FML", "+fp16fml,+fullfp16,+fp-armv8,+neo
 def : FMVExtension<"frintts", "FEAT_FRINTTS", "+fptoint", 250>;
 def : FMVExtension<"i8mm", "FEAT_I8MM", "+i8mm", 270>;
 def : FMVExtension<"jscvt", "FEAT_JSCVT", "+fp-armv8,+neon,+jsconv", 210>;
-def : FMVExtension<"ls64", "FEAT_LS64", "", 520>;
-def : FMVExtension<"ls64_accdata", "FEAT_LS64_ACCDATA", "+ls64", 540>;
-def : FMVExtension<"ls64_v", "FEAT_LS64_V", "", 530>;
+def : FMVExtension<"ls64", "FEAT_LS64", "+ls64", 520>;
+def : FMVExtension<"ls64_accdata", "FEAT_LS64_ACCDATA", "+ls64,+ls64_v,+ls64_accdata", 540>;
+def : FMVExtension<"ls64_v", "FEAT_LS64_V", "+ls64,+ls64_v", 530>;
 def : FMVExtension<"lse", "FEAT_LSE", "+lse", 80>;
 def : FMVExtension<"memtag", "FEAT_MEMTAG", "", 440>;
 def : FMVExtension<"memtag2", "FEAT_MEMTAG2", "+mte", 450>;
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index a1ae0873fc1902..2e672dc016bdba 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -305,9 +305,17 @@ def FeatureWFxT : ExtensionWithMArch<"wfxt", "WFxT", "FEAT_WFxT",
 def FeatureHCX : Extension<"hcx", "HCX", "FEAT_HCX",
   "Enable Armv8.7-A HCRX_EL2 system register">;
 
-def FeatureLS64 : ExtensionWithMArch<"ls64", "LS64",
-  "FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA",
-  "Enable Armv8.7-A LD64B/ST64B Accelerator Extension">;
+def FeatureLS64 : Extension<"ls64", "LS64", "FEAT_LS64",
+  "Enable single-copy atomic 64-byte loads and stores without status result">;
+
+def FeatureLS64_V : Extension<"ls64_v", "LS64_V", "FEAT_LS64_V",
+  "Enable single-copy atomic 64-byte stores with status result",
+  [FeatureLS64]>;
+
+let UserVisibleName = "ls64" in
+def FeatureLS64_ACCDATA : ExtensionWithMArch<"ls64_accdata", "LS64_ACCDATA", "FEAT_LS64_ACCDATA",
+  "Enable single-copy atomic 64-byte EL0 stores with status result",
+  [FeatureLS64_V]>;
 
 def FeatureSPE_EEF : Extension<"spe-eef", "SPE_EEF", "FEAT_SPEv1p2",
   "Enable extra register in the Statistical Profiling Extension">;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 1053ba9242768a..fc8cfb5fbf66b1 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -284,6 +284,10 @@ def HasWFxT          : Predicate<"Subtarget->hasWFxT()">,
                        AssemblerPredicateWithAll<(all_of FeatureWFxT), "wfxt">;
 def HasLS64          : Predicate<"Subtarget->hasLS64()">,
                        AssemblerPredicateWithAll<(all_of FeatureLS64), "ls64">;
+def HasLS64_V        : Predicate<"Subtarget->hasLS64_V()">,
+                       AssemblerPredicateWithAll<(all_of FeatureLS64_V), "ls64_v">;
+def HasLS64_ACCDATA  : Predicate<"Subtarget->hasLS64_ACCDATA()">,
+                       AssemblerPredicateWithAll<(all_of FeatureLS64_ACCDATA), "ls64_accdata">;
 def HasBRBE          : Predicate<"Subtarget->hasBRBE()">,
                        AssemblerPredicateWithAll<(all_of FeatureBRBE), "brbe">;
 def HasSPE_EEF       : Predicate<"Subtarget->hasSPE_EEF()">,
@@ -9825,20 +9829,25 @@ foreach i = 0-7 in {
             (EXTRACT_SUBREG $val, !cast<SubRegIndex>("x8sub_"#i))>;
 }
 
+class ST64BPattern<Intrinsic intrinsic, Instruction instruction>
+  : Pat<(intrinsic GPR64sp:$addr, GPR64:$x0, GPR64:$x1, GPR64:$x2, GPR64:$x3, GPR64:$x4, GPR64:$x5, GPR64:$x6, GPR64:$x7),
+        (instruction (REG_SEQUENCE GPR64x8Class, $x0, x8sub_0, $x1, x8sub_1, $x2, x8sub_2, $x3, x8sub_3, $x4, x8sub_4, $x5, x8sub_5, $x6, x8sub_6, $x7, x8sub_7), $addr)>;
+
 let Predicates = [HasLS64] in {
   def LD64B: LoadStore64B<0b101, "ld64b", (ins GPR64sp:$Rn),
                                           (outs GPR64x8:$Rt)>;
   def ST64B: LoadStore64B<0b001, "st64b", (ins GPR64x8:$Rt, GPR64sp:$Rn),
                                           (outs)>;
-  def ST64BV:   Store64BV<0b011, "st64bv">;
-  def ST64BV0:  Store64BV<0b010, "st64bv0">;
-
-  class ST64BPattern<Intrinsic intrinsic, Instruction instruction>
-    : Pat<(intrinsic GPR64sp:$addr, GPR64:$x0, GPR64:$x1, GPR64:$x2, GPR64:$x3, GPR64:$x4, GPR64:$x5, GPR64:$x6, GPR64:$x7),
-          (instruction (REG_SEQUENCE GPR64x8Class, $x0, x8sub_0, $x1, x8sub_1, $x2, x8sub_2, $x3, x8sub_3, $x4, x8sub_4, $x5, x8sub_5, $x6, x8sub_6, $x7, x8sub_7), $addr)>;
-
   def : ST64BPattern<int_aarch64_st64b, ST64B>;
+}
+
+let Predicates = [HasLS64_V] in {
+  def ST64BV:   Store64BV<0b011, "st64bv">;
   def : ST64BPattern<int_aarch64_st64bv, ST64BV>;
+}
+
+let Predicates = [HasLS64_ACCDATA] in {
+  def ST64BV0:  Store64BV<0b010, "st64bv0">;
   def : ST64BPattern<int_aarch64_st64bv0, ST64BV0>;
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64Processors.td b/llvm/lib/Target/AArch64/AArch64Processors.td
index 71384a23c49afc..70726ad33028b4 100644
--- a/llvm/lib/Target/AArch64/AArch64Processors.td
+++ b/llvm/lib/Target/AArch64/AArch64Processors.td
@@ -945,7 +945,7 @@ def ProcessorFeatures {
                                        FeatureComplxNum, FeatureCRC, FeatureFPARMv8, FeatureJS, FeatureLSE,
                                        FeaturePAuth, FeatureRAS, FeatureRCPC, FeatureRDM];
   list<SubtargetFeature> NeoverseV3 = [HasV9_2aOps, FeatureETE, FeatureFP16FML,
-                                      FeatureFullFP16, FeatureLS64, FeatureMTE,
+                                      FeatureFullFP16, FeatureLS64_ACCDATA, FeatureMTE,
                                       FeaturePerfMon, FeatureRandGen, FeatureSPE,
                                       FeatureSPE_EEF, FeatureSVE2BitPerm, FeatureBRBE,
                                       FeatureSSBS, FeatureSB, FeaturePredRes, FeaturePAuth, FeatureFlagM,
@@ -953,7 +953,7 @@ def ProcessorFeatures {
                                       FeatureDotProd, FeatureFPARMv8, FeatureMatMulInt8, FeatureJS, FeatureLSE,
                                       FeatureNEON, FeatureRAS, FeatureRCPC, FeatureRDM, FeatureRME];
   list<SubtargetFeature> NeoverseV3AE = [HasV9_2aOps, FeatureETE, FeatureFP16FML,
-                                      FeatureFullFP16, FeatureLS64, FeatureMTE,
+                                      FeatureFullFP16, FeatureLS64_ACCDATA, FeatureMTE,
                                       FeaturePerfMon, FeatureRandGen, FeatureSPE,
                                       FeatureSPE_EEF, FeatureSVE2BitPerm, FeatureBRBE,
                                       FeatureSSBS, FeatureSB, FeaturePredRes, FeaturePAuth, FeatureFlagM,
diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
index 0b5bc97674c768..253de2df603f69 100644
--- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td
+++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td
@@ -1720,7 +1720,7 @@ def : ROSysReg<"CNTVCTSS_EL0",     0b11, 0b011, 0b1110, 0b0000, 0b110>;
 }
 
 // v8.7a LD64B/ST64B Accelerator Extension system register
-let Requires = [{ {AArch64::FeatureLS64} }] in
+let Requires = [{ {AArch64::FeatureLS64_ACCDATA} }] in
 def : RWSysReg<"ACCDATA_EL1",       0b11, 0b000, 0b1101, 0b0000, 0b101>;
 
 // Branch Record Buffer system registers
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 5e17ed40df8aba..4bbd8e95e023ad 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3682,6 +3682,8 @@ static const struct Extension {
     {"sve2p1", {AArch64::FeatureSVE2p1}},
     {"b16b16", {AArch64::FeatureB16B16}},
     {"ls64", {AArch64::FeatureLS64}},
+    {"ls64_v", {AArch64::FeatureLS64_V}},
+    {"ls64_accdata", {AArch64::FeatureLS64_ACCDATA}},
     {"xs", {AArch64::FeatureXS}},
     {"pauth", {AArch64::FeaturePAuth}},
     {"flagm", {AArch64::FeatureFlagM}},
diff --git a/llvm/test/CodeGen/AArch64/ls64-intrinsics.ll b/llvm/test/CodeGen/AArch64/ls64-intrinsics.ll
index 0f6f2d1221d6c3..7d541461ce281f 100644
--- a/llvm/test/CodeGen/AArch64/ls64-intrinsics.ll
+++ b/llvm/test/CodeGen/AArch64/ls64-intrinsics.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64 -mattr=+ls64 -verify-machineinstrs -o - %s | FileCheck %s
-; RUN: llc -mtriple=aarch64_be -mattr=+ls64 -verify-machineinstrs -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64 -mattr=+ls64_accdata -verify-machineinstrs -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64_be -mattr=+ls64_accdata -verify-machineinstrs -o - %s | FileCheck %s
 
 define void @test_ld64b(ptr %out, ptr %addr) {
 ; CHECK-LABEL: test_ld64b:
diff --git a/llvm/test/MC/AArch64/armv8.7a-ls64.s b/llvm/test/MC/AArch64/armv8.7a-ls64.s
index d4684e38cbea28..39e9112c7df6cb 100644
--- a/llvm/test/MC/AArch64/armv8.7a-ls64.s
+++ b/llvm/test/MC/AArch64/armv8.7a-ls64.s
@@ -1,4 +1,4 @@
-// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+ls64 < %s 2>%t | FileCheck %s
+// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+ls64_accdata < %s 2>%t | FileCheck %s
 // RUN: FileCheck --check-prefix=CHECK-ERR %s < %t
 // RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2> %t
 // RUN: FileCheck --check-prefixes=CHECK-ERR,CHECK-NO-LS64-ERR %s < %t
diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.7a-ls64.txt b/llvm/test/MC/Disassembler/AArch64/armv8.7a-ls64.txt
index d307b128835ff1..be30317f628d08 100644
--- a/llvm/test/MC/Disassembler/AArch64/armv8.7a-ls64.txt
+++ b/llvm/test/MC/Disassembler/AArch64/armv8.7a-ls64.txt
@@ -1,4 +1,4 @@
-# RUN: not llvm-mc -triple=aarch64 -mattr=+ls64 -disassemble %s 2> %t | FileCheck %s
+# RUN: not llvm-mc -triple=aarch64 -mattr=+ls64_accdata -disassemble %s 2> %t | FileCheck %s
 # RUN: FileCheck --check-prefix=CHECK-ERR %s < %t
 # RUN: not llvm-mc -triple=aarch64 -disassemble %s 2> %t | FileCheck --check-prefix=CHECK-NO-LS64 %s
 # RUN: FileCheck --check-prefix=CHECK-ERR --check-prefix=CHECK-NO-LS64-ERR %s < %t
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index 3d55b0309d26fd..e887ff18e9baff 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1345,40 +1345,40 @@ INSTANTIATE_TEST_SUITE_P(
                               AArch64::AEK_PAUTH,       AArch64::AEK_PERFMON,
                               AArch64::AEK_ETE}),
         AArch64CPUTestParams("neoverse-v3", "armv9.2-a",
-                             {AArch64::AEK_BF16,        AArch64::AEK_I8MM,
-                              AArch64::AEK_SVE,         AArch64::AEK_SVE2,
-                              AArch64::AEK_FP16,        AArch64::AEK_DOTPROD,
-                              AArch64::AEK_LSE,         AArch64::AEK_RDM,
-                              AArch64::AEK_SIMD,        AArch64::AEK_RCPC,
-                              AArch64::AEK_RAS,         AArch64::AEK_CRC,
-                              AArch64::AEK_FP,          AArch64::AEK_PROFILE,
-                              AArch64::AEK_MTE,         AArch64::AEK_SSBS,
-                              AArch64::AEK_SB,          AArch64::AEK_PREDRES,
-                              AArch64::AEK_LS64,        AArch64::AEK_BRBE,
-                              AArch64::AEK_PAUTH,       AArch64::AEK_FLAGM,
-                              AArch64::AEK_PERFMON,     AArch64::AEK_RAND,
-                              AArch64::AEK_SVE2BITPERM, AArch64::AEK_FP16FML,
-                              AArch64::AEK_PROFILE,     AArch64::AEK_JSCVT,
-                              AArch64::AEK_FCMA,        AArch64::AEK_PERFMON,
-                              AArch64::AEK_ETE,         AArch64::AEK_SPE_EEF,
+                             {AArch64::AEK_BF16,         AArch64::AEK_I8MM,
+                              AArch64::AEK_SVE,          AArch64::AEK_SVE2,
+                              AArch64::AEK_FP16,         AArch64::AEK_DOTPROD,
+                              AArch64::AEK_LSE,          AArch64::AEK_RDM,
+                              AArch64::AEK_SIMD,         AArch64::AEK_RCPC,
+                              AArch64::AEK_RAS,          AArch64::AEK_CRC,
+                              AArch64::AEK_FP,           AArch64::AEK_PROFILE,
+                              AArch64::AEK_MTE,          AArch64::AEK_SSBS,
+                              AArch64::AEK_SB,           AArch64::AEK_PREDRES,
+                              AArch64::AEK_LS64_ACCDATA, AArch64::AEK_BRBE,
+                              AArch64::AEK_PAUTH,        AArch64::AEK_FLAGM,
+                              AArch64::AEK_PERFMON,      AArch64::AEK_RAND,
+                              AArch64::AEK_SVE2BITPERM,  AArch64::AEK_FP16FML,
+                              AArch64::AEK_PROFILE,      AArch64::AEK_JSCVT,
+                              AArch64::AEK_FCMA,         AArch64::AEK_PERFMON,
+                              AArch64::AEK_ETE,          AArch64::AEK_SPE_EEF,
                               AArch64::AEK_RME}),
         AArch64CPUTestParams("neoverse-v3ae", "armv9.2-a",
-                             {AArch64::AEK_BF16,        AArch64::AEK_I8MM,
-                              AArch64::AEK_SVE,         AArch64::AEK_SVE2,
-                              AArch64::AEK_FP16,        AArch64::AEK_DOTPROD,
-                              AArch64::AEK_LSE,         AArch64::AEK_RDM,
-                              AArch64::AEK_SIMD,        AArch64::AEK_RCPC,
-                              AArch64::AEK_RAS,         AArch64::AEK_CRC,
-                              AArch64::AEK_FP,          AArch64::AEK_PROFILE,
-                              AArch64::AEK_MTE,         AArch64::AEK_SSBS,
-                              AArch64::AEK_SB,          AArch64::AEK_PREDRES,
-                              AArch64::AEK_LS64,        AArch64::AEK_BRBE,
-                              AArch64::AEK_PAUTH,       AArch64::AEK_FLAGM,
-                              AArch64::AEK_PERFMON,     AArch64::AEK_RAND,
-                              AArch64::AEK_SVE2BITPERM, AArch64::AEK_FP16FML,
-                              AArch64::AEK_PROFILE,     AArch64::AEK_JSCVT,
-                              AArch64::AEK_FCMA,        AArch64::AEK_PERFMON,
-                              AArch64::AEK_ETE,         AArch64::AEK_SPE_EEF,
+                             {AArch64::AEK_BF16,         AArch64::AEK_I8MM,
+                              AArch64::AEK_SVE,          AArch64::AEK_SVE2,
+                              AArch64::AEK_FP16,         AArch64::AEK_DOTPROD,
+                              AArch64::AEK_LSE,          AArch64::AEK_RDM,
+                              AArch64::AEK_SIMD,         AArch64::AEK_RCPC,
+                              AArch64::AEK_RAS,          AArch64::AEK_CRC,
+                              AArch64::AEK_FP,           AArch64::AEK_PROFILE,
+                              AArch64::AEK_MTE,          AArch64::AEK_SSBS,
+                              AArch64::AEK_SB,           AArch64::AEK_PREDRES,
+                              AArch64::AEK_LS64_ACCDATA, AArch64::AEK_BRBE,
+                              AArch64::AEK_PAUTH,        AArch64::AEK_FLAGM,
+                              AArch64::AEK_PERFMON,      AArch64::AEK_RAND,
+                              AArch64::AEK_SVE2BITPERM,  AArch64::AEK_FP16FML,
+                              AArch64::AEK_PROFILE,      AArch64::AEK_JSCVT,
+                              AArch64::AEK_FCMA,         AArch64::AEK_PERFMON,
+                              AArch64::AEK_ETE,          AArch64::AEK_SPE_EEF,
                               AArch64::AEK_RME}),
         AArch64CPUTestParams(
             "cortex-r82", "armv8-r",
@@ -1984,7 +1984,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
       AArch64::AEK_PREDRES,      AArch64::AEK_BF16,
       AArch64::AEK_I8MM,         AArch64::AEK_F32MM,
       AArch64::AEK_F64MM,        AArch64::AEK_TME,
-      AArch64::AEK_LS64,         AArch64::AEK_BRBE,
+      AArch64::AEK_LS64,         AArch64::AEK_LS64_ACCDATA,
+      AArch64::AEK_LS64_V,       AArch64::AEK_BRBE,
       AArch64::AEK_PAUTH,        AArch64::AEK_FLAGM,
       AArch64::AEK_SME,          AArch64::AEK_SMEF64F64,
       AArch64::AEK_SMEI16I64,    AArch64::AEK_SME2,
@@ -2056,6 +2057,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
   EXPECT_TRUE(llvm::is_contained(Features, "+f64mm"));
   EXPECT_TRUE(llvm::is_contained(Features, "+tme"));
   EXPECT_TRUE(llvm::is_contained(Features, "+ls64"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+ls64_accdata"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+ls64_v"));
   EXPECT_TRUE(llvm::is_contained(Features, "+brbe"));
   EXPECT_TRUE(llvm::is_contained(Features, "+pauth"));
   EXPECT_TRUE(llvm::is_contained(Features, "+flagm"));

>From 164041ae7ef46b92a4e1fabcf5a3744cb81ce3e5 Mon Sep 17 00:00:00 2001
From: Alexandros Lamprineas <alexandros.lamprineas at arm.com>
Date: Wed, 18 Sep 2024 11:03:08 +0100
Subject: [PATCH 2/2] Changes from last revision:

* Transitively disable all three LS64_ACCDATA, LS64_V, LS64
  both on the command line and the assembler directive.
* Test the above.
* Remove redundant HasLS64_V and HasLS64_ACCDATA variables from clang.
---
 clang/lib/Basic/Targets/AArch64.cpp             | 15 ++-------------
 clang/lib/Basic/Targets/AArch64.h               |  2 --
 clang/test/CodeGen/aarch64-ls64-inline-asm.c    |  2 +-
 clang/test/Driver/aarch64-ls64.c                |  8 ++++++++
 .../AArch64/AsmParser/AArch64AsmParser.cpp      |  6 +++---
 llvm/lib/TargetParser/AArch64TargetParser.cpp   |  8 ++++++++
 .../AArch64/directive-arch_extension-negative.s | 17 ++++++++++++++++-
 7 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 30f72eba2ca1da..f846be49332ee4 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -779,9 +779,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
       .Case("predres", HasPredRes)
       .Cases("ssbs", "ssbs2", HasSSBS)
       .Case("bti", HasBTI)
-      .Case("ls64", HasLS64)
-      .Case("ls64_v", HasLS64_V)
-      .Case("ls64_accdata", HasLS64_ACCDATA)
+      .Cases("ls64", "ls64_v", "ls64_accdata", HasLS64)
       .Case("wfxt", HasWFxT)
       .Case("rcpc3", HasRCPC3)
       .Default(false);
@@ -1073,17 +1071,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       HasBFloat16 = true;
     if (Feature == "+lse")
       HasLSE = true;
-    if (Feature == "+ls64")
+    if (Feature == "+ls64_accdata")
       HasLS64 = true;
-    if (Feature == "+ls64_v") {
-      HasLS64 = true;
-      HasLS64_V = true;
-    }
-    if (Feature == "+ls64_accdata") {
-      HasLS64 = true;
-      HasLS64_V = true;
-      HasLS64_ACCDATA = true;
-    }
     if (Feature == "+rand")
       HasRandGen = true;
     if (Feature == "+flagm")
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 126f6e616d77c4..526f7f30a38618 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -45,8 +45,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
   bool HasTME = false;
   bool HasPAuth = false;
   bool HasLS64 = false;
-  bool HasLS64_V = false;
-  bool HasLS64_ACCDATA = false;
   bool HasRandGen = false;
   bool HasMatMul = false;
   bool HasBFloat16 = false;
diff --git a/clang/test/CodeGen/aarch64-ls64-inline-asm.c b/clang/test/CodeGen/aarch64-ls64-inline-asm.c
index a01393525bcd42..f3b98b27e7f466 100644
--- a/clang/test/CodeGen/aarch64-ls64-inline-asm.c
+++ b/clang/test/CodeGen/aarch64-ls64-inline-asm.c
@@ -1,5 +1,5 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
-// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -O1 -emit-llvm -x c %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64_accdata -O1 -emit-llvm -x c %s -o - | FileCheck %s
 
 struct foo { unsigned long long x[8]; };
 
diff --git a/clang/test/Driver/aarch64-ls64.c b/clang/test/Driver/aarch64-ls64.c
index 7d828a22c60fd8..5b37d690a2fda0 100644
--- a/clang/test/Driver/aarch64-ls64.c
+++ b/clang/test/Driver/aarch64-ls64.c
@@ -2,6 +2,8 @@
 
 // RUN: %clang -### --target=aarch64-none-elf -march=armv8.7-a+ls64 %s 2>&1 | FileCheck %s
 // CHECK: "-target-feature" "+ls64"
+// CHECK: "-target-feature" "+ls64_accdata"
+// CHECK: "-target-feature" "+ls64_v"
 
 // RUN: %clang -### --target=aarch64-none-elf -march=armv8.7-a+nols64 %s 2>&1 | FileCheck %s --check-prefix=ABSENT_LS64
 
@@ -11,3 +13,9 @@
 // RUN: %clang -### --target=aarch64-none-elf -march=armv8.7-a %s 2>&1 | FileCheck %s --check-prefix=ABSENT_LS64
 // ABSENT_LS64-NOT: "-target-feature" "+ls64"
 // ABSENT_LS64-NOT: "-target-feature" "-ls64"
+
+// Test that nols64 disables all three FEAT_LS64, FEAT_LS64_V and FEAT_LS64_ACCDATA.
+// RUN: %clang -### --target=aarch64-none-elf -march=armv8.7-a+ls64+nols64 %s 2>&1 | FileCheck %s --check-prefix=NOLS64
+// NOLS64: "-target-feature" "-ls64"
+// NOLS64: "-target-feature" "-ls64_accdata"
+// NOLS64: "-target-feature" "-ls64_v"
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index fcd924c03df8c1..577fd612255ae1 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3681,9 +3681,9 @@ static const struct Extension {
     {"sve2-sha3", {AArch64::FeatureSVE2SHA3}},
     {"sve2-bitperm", {AArch64::FeatureSVE2BitPerm}},
     {"sve2p1", {AArch64::FeatureSVE2p1}},
-    {"ls64", {AArch64::FeatureLS64}},
-    {"ls64_v", {AArch64::FeatureLS64_V}},
-    {"ls64_accdata", {AArch64::FeatureLS64_ACCDATA}},
+    {"ls64",
+     {AArch64::FeatureLS64, AArch64::FeatureLS64_V,
+      AArch64::FeatureLS64_ACCDATA}},
     {"xs", {AArch64::FeatureXS}},
     {"pauth", {AArch64::FeaturePAuth}},
     {"flagm", {AArch64::FeatureFlagM}},
diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp
index 9fc7201efac6e2..41a6247146b9ec 100644
--- a/llvm/lib/TargetParser/AArch64TargetParser.cpp
+++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp
@@ -253,6 +253,14 @@ void AArch64::ExtensionSet::disable(ArchExtKind E) {
     disable(AEK_SM4);
   }
 
+  // FEAT_LS64, FEAT_LS64_V and FEAT_LS64_ACCDATA were historically lumped under
+  // the name 'ls64'. Therefore 'nols64' should disable all three even though
+  // their dependencies are not transitive.
+  if (E == AEK_LS64_ACCDATA) {
+    disable(AEK_LS64_V);
+    disable(AEK_LS64);
+  }
+
   if (!Enabled.test(E))
     return;
 
diff --git a/llvm/test/MC/AArch64/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/directive-arch_extension-negative.s
index 1843af56555461..ff0df7cbf04bd4 100644
--- a/llvm/test/MC/AArch64/directive-arch_extension-negative.s
+++ b/llvm/test/MC/AArch64/directive-arch_extension-negative.s
@@ -1,5 +1,5 @@
 // RUN: not llvm-mc -triple aarch64 \
-// RUN: -mattr=+crc,+sm4,+sha3,+sha2,+aes,+fp,+neon,+ras,+lse,+predres,+ccdp,+mte,+tlb-rmi,+pan-rwv,+ccpp,+rcpc,+ls64,+flagm,+hbc,+mops \
+// RUN: -mattr=+crc,+sm4,+sha3,+sha2,+aes,+fp,+neon,+ras,+lse,+predres,+ccdp,+mte,+tlb-rmi,+pan-rwv,+ccpp,+rcpc,+ls64_accdata,+flagm,+hbc,+mops \
 // RUN: -mattr=+rcpc3,+lse128,+d128,+the,+rasv2,+ite,+cssc,+specres2,+gcs \
 // RUN: -filetype asm -o - %s 2>&1 | FileCheck %s
 
@@ -150,10 +150,25 @@ stilp w24, w0, [x16, #-8]!
 
 ld64b x0, [x13]
 // CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: ls64
+st64b x0, [x13]
+// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: ls64
+st64bv x8, x0, [x13]
+// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: ls64_v
+st64bv0 x8, x0, [x13]
+// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: ls64_accdata
 .arch_extension nols64
 ld64b x0, [x13]
 // CHECK: [[@LINE-1]]:1: error: instruction requires: ls64
 // CHECK-NEXT: ld64b x0, [x13]
+st64b x0, [x13]
+// CHECK: [[@LINE-1]]:1: error: instruction requires: ls64
+// CHECK-NEXT: st64b x0, [x13]
+st64bv x8, x0, [x13]
+// CHECK: [[@LINE-1]]:1: error: instruction requires: ls64_v
+// CHECK-NEXT: st64bv x8, x0, [x13]
+st64bv0 x8, x0, [x13]
+// CHECK: [[@LINE-1]]:1: error: instruction requires: ls64_accdata
+// CHECK-NEXT: st64bv0 x8, x0, [x13]
 
 cfinv
 // CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: flagm



More information about the cfe-commits mailing list