[clang] [llvm] [Clang][SME] Detect always_inline used with mismatched streaming attributes (PR #77936)

Sam Tebbs via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 21 07:45:43 PST 2024


https://github.com/SamTebbs33 updated https://github.com/llvm/llvm-project/pull/77936

>From 7314429a203900a8f555e1b0471fdd4cfd4d8d03 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 10 Jan 2024 14:57:04 +0000
Subject: [PATCH 01/18] [Clang][SME] Detect always_inline used with mismatched
 streaming attributes

This patch adds an error that is emitted when a streaming function is
marked as always_inline and is called from a non-streaming function.
---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 ++
 clang/include/clang/Sema/Sema.h               |  9 +++++++
 clang/lib/CodeGen/CMakeLists.txt              |  1 +
 clang/lib/CodeGen/Targets/AArch64.cpp         | 20 ++++++++++++++
 clang/lib/Sema/SemaChecking.cpp               | 27 +++++++------------
 ...-sme-func-attrs-inline-locally-streaming.c | 12 +++++++++
 .../aarch64-sme-func-attrs-inline-streaming.c | 12 +++++++++
 7 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 85ecfdf9de62d4..2d0f971858840d 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -279,6 +279,8 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
 def err_function_needs_feature : Error<
   "always_inline function %1 requires target feature '%2', but would "
   "be inlined into function %0 that is compiled without support for '%2'">;
+def err_function_alwaysinline_attribute_mismatch : Error<
+  "always_inline function %1 and its caller %0 have mismatched %2 attributes">;
 
 def warn_avx_calling_convention
     : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6ce422d66ae5b0..dd75b5aad3d9c8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13832,8 +13832,17 @@ class Sema final {
     FormatArgumentPassingKind ArgPassingKind;
   };
 
+enum ArmStreamingType {
+  ArmNonStreaming,
+  ArmStreaming,
+  ArmStreamingCompatible,
+  ArmStreamingOrSVE2p1
+};
+
+
   static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
                                   bool IsVariadic, FormatStringInfo *FSI);
+  static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
 
 private:
   void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 52216d93a302bb..03a6f2f1d7a9d2 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -151,4 +151,5 @@ add_clang_library(clangCodeGen
   clangFrontend
   clangLex
   clangSerialization
+  clangSema
   )
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index ee7f95084d2e0b..4018f91422e358 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -8,6 +8,8 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Sema/Sema.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -155,6 +157,11 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
     }
     return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty);
   }
+
+  void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
+                            const FunctionDecl *Caller,
+                            const FunctionDecl *Callee,
+                            const CallArgList &Args) const override;
 };
 
 class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
@@ -814,6 +821,19 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
                           /*allowHigherAlign*/ false);
 }
 
+void AArch64TargetCodeGenInfo::checkFunctionCallABI(
+    CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
+    const FunctionDecl *Callee, const CallArgList &Args) const {
+    if (!Callee->hasAttr<AlwaysInlineAttr>())
+      return;
+
+    auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
+    auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
+
+    if (CalleeIsStreaming && !CallerIsStreaming)
+        CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming";
+}
+
 std::unique_ptr<TargetCodeGenInfo>
 CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
                                         AArch64ABIKind Kind) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ace3e386988f00..a92db7d67e1cbd 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2998,13 +2998,6 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
   llvm_unreachable("Invalid NeonTypeFlag!");
 }
 
-enum ArmStreamingType {
-  ArmNonStreaming,
-  ArmStreaming,
-  ArmStreamingCompatible,
-  ArmStreamingOrSVE2p1
-};
-
 bool Sema::ParseSVEImmChecks(
     CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
   // Perform all the immediate checks for this builtin call.
@@ -3145,7 +3138,7 @@ bool Sema::ParseSVEImmChecks(
   return HasError;
 }
 
-static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
+Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) {
   if (FD->hasAttr<ArmLocallyStreamingAttr>())
     return ArmStreaming;
   if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
@@ -3159,31 +3152,31 @@ static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
 
 static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
                                      const FunctionDecl *FD,
-                                     ArmStreamingType BuiltinType) {
-  ArmStreamingType FnType = getArmStreamingFnType(FD);
-  if (BuiltinType == ArmStreamingOrSVE2p1) {
+                                     Sema::ArmStreamingType BuiltinType) {
+  Sema::ArmStreamingType FnType = Sema::getArmStreamingFnType(FD);
+  if (BuiltinType == Sema::ArmStreamingOrSVE2p1) {
     // Check intrinsics that are available in [sve2p1 or sme/sme2].
     llvm::StringMap<bool> CallerFeatureMap;
     S.Context.getFunctionFeatureMap(CallerFeatureMap, FD);
     if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap))
-      BuiltinType = ArmStreamingCompatible;
+      BuiltinType = Sema::ArmStreamingCompatible;
     else
-      BuiltinType = ArmStreaming;
+      BuiltinType = Sema::ArmStreaming;
   }
 
-  if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) {
+  if (FnType == Sema::ArmStreaming && BuiltinType == Sema::ArmNonStreaming) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "streaming";
   }
 
-  if (FnType == ArmStreamingCompatible &&
-      BuiltinType != ArmStreamingCompatible) {
+  if (FnType == Sema::ArmStreamingCompatible &&
+      BuiltinType != Sema::ArmStreamingCompatible) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "streaming compatible";
     return;
   }
 
-  if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) {
+  if (FnType == Sema::ArmNonStreaming && BuiltinType == Sema::ArmStreaming) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "non-streaming";
   }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
new file mode 100644
index 00000000000000..4aa9fbf4a8fa18
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
@@ -0,0 +1,12 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+// Conflicting attributes when using always_inline
+__attribute__((always_inline)) __arm_locally_streaming
+int inlined_fn_local(void) {
+    return 42;
+}
+// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+int inlined_fn_caller(void) { return inlined_fn_local(); }
+__arm_locally_streaming
+int inlined_fn_caller_local(void) { return inlined_fn_local(); }
+int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_local(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c
new file mode 100644
index 00000000000000..7268a49bb2491d
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c
@@ -0,0 +1,12 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+// Conflicting attributes when using always_inline
+__attribute__((always_inline))
+int inlined_fn_streaming(void) __arm_streaming {
+    return 42;
+}
+// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+int inlined_fn_caller(void) { return inlined_fn_streaming(); }
+__arm_locally_streaming
+int inlined_fn_caller_local(void) { return inlined_fn_streaming(); }
+int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming(); }

>From 04866d0c0be106a3d0296938f5e1b1d5f9e2591e Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Fri, 12 Jan 2024 15:13:28 +0000
Subject: [PATCH 02/18] fixup: formatting

---
 clang/include/clang/Sema/Sema.h       | 13 ++++++-------
 clang/lib/CodeGen/Targets/AArch64.cpp | 16 ++++++++++------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index dd75b5aad3d9c8..1ee065e7de9b15 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13832,13 +13832,12 @@ class Sema final {
     FormatArgumentPassingKind ArgPassingKind;
   };
 
-enum ArmStreamingType {
-  ArmNonStreaming,
-  ArmStreaming,
-  ArmStreamingCompatible,
-  ArmStreamingOrSVE2p1
-};
-
+  enum ArmStreamingType {
+    ArmNonStreaming,
+    ArmStreaming,
+    ArmStreamingCompatible,
+    ArmStreamingOrSVE2p1
+  };
 
   static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
                                   bool IsVariadic, FormatStringInfo *FSI);
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 4018f91422e358..fe7b384c721d69 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -824,14 +824,18 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
 void AArch64TargetCodeGenInfo::checkFunctionCallABI(
     CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
     const FunctionDecl *Callee, const CallArgList &Args) const {
-    if (!Callee->hasAttr<AlwaysInlineAttr>())
-      return;
+  if (!Callee->hasAttr<AlwaysInlineAttr>())
+    return;
 
-    auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
-    auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
+  auto CalleeIsStreaming =
+      Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
+  auto CallerIsStreaming =
+      Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
 
-    if (CalleeIsStreaming && !CallerIsStreaming)
-        CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming";
+  if (CalleeIsStreaming && !CallerIsStreaming)
+    CGM.getDiags().Report(CallLoc,
+                          diag::err_function_alwaysinline_attribute_mismatch)
+        << Caller->getDeclName() << Callee->getDeclName() << "streaming";
 }
 
 std::unique_ptr<TargetCodeGenInfo>

>From 156c96bc9660472c17c666ff465613d7276e0db9 Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Mon, 15 Jan 2024 11:32:44 +0000
Subject: [PATCH 03/18] fixup: allow streaming compatible callee and check if
 modes are the same

---
 clang/lib/CodeGen/Targets/AArch64.cpp           | 11 ++++++-----
 .../sme-inline-streaming-compatible-caller.c    |  9 +++++++++
 .../sme-inline-streaming-compatible.c           | 17 +++++++++++++++++
 .../sme-inline-streaming-locally.c}             |  0
 .../sme-inline-streaming.c}                     |  0
 5 files changed, 32 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
 rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-locally-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c} (100%)
 rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming.c} (100%)

diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index fe7b384c721d69..72f70c931fd9e6 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -827,12 +827,13 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   if (!Callee->hasAttr<AlwaysInlineAttr>())
     return;
 
-  auto CalleeIsStreaming =
-      Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
-  auto CallerIsStreaming =
-      Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
+  auto CalleeStreamingMode = Sema::getArmStreamingFnType(Callee);
+  auto CallerStreamingMode = Sema::getArmStreamingFnType(Caller);
 
-  if (CalleeIsStreaming && !CallerIsStreaming)
+  // The caller can inline the callee if their streaming modes match or the
+  // callee is streaming compatible
+  if (CalleeStreamingMode != CallerStreamingMode &&
+      CalleeStreamingMode != Sema::ArmStreamingCompatible)
     CGM.getDiags().Report(CallLoc,
                           diag::err_function_alwaysinline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
new file mode 100644
index 00000000000000..5c1779291a7e5b
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
@@ -0,0 +1,9 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+// Conflicting attributes when using always_inline
+__attribute__((always_inline))
+int inlined_fn_streaming(void) __arm_streaming {
+    return 42;
+}
+// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+int inlined_fn_caller(void) __arm_streaming_compatible { return inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
new file mode 100644
index 00000000000000..a996c429fdda0d
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -0,0 +1,17 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+// Conflicting attributes when using always_inline
+__attribute__((always_inline))
+int inlined_fn_streaming_compatible(void) __arm_streaming_compatible {
+    return 42;
+}
+__attribute__((always_inline))
+int inlined_fn(void) {
+    return 42;
+}
+int inlined_fn_caller(void) { return inlined_fn_streaming_compatible(); }
+__arm_locally_streaming
+int inlined_fn_caller_local(void) { return inlined_fn_streaming_compatible(); }
+int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming_compatible(); }
+// expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}}
+int inlined_fn_caller_compatible(void) __arm_streaming_compatible { return inlined_fn(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
similarity index 100%
rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
similarity index 100%
rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c
rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c

>From 5428dd7ed0745fd58cec768cc12742c40b86ce60 Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Mon, 15 Jan 2024 16:14:00 +0000
Subject: [PATCH 04/18] fixup: rename error

---
 clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 +-
 clang/lib/CodeGen/Targets/AArch64.cpp                | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 2d0f971858840d..27149553c79a2a 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -279,7 +279,7 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
 def err_function_needs_feature : Error<
   "always_inline function %1 requires target feature '%2', but would "
   "be inlined into function %0 that is compiled without support for '%2'">;
-def err_function_alwaysinline_attribute_mismatch : Error<
+def err_function_always_inline_attribute_mismatch : Error<
   "always_inline function %1 and its caller %0 have mismatched %2 attributes">;
 
 def warn_avx_calling_convention
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 72f70c931fd9e6..8d9f840c018fa5 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -835,7 +835,7 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   if (CalleeStreamingMode != CallerStreamingMode &&
       CalleeStreamingMode != Sema::ArmStreamingCompatible)
     CGM.getDiags().Report(CallLoc,
-                          diag::err_function_alwaysinline_attribute_mismatch)
+                          diag::err_function_always_inline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
 }
 

>From 3b5451c8743a9f5a00d460c6a8eb998b6acaedc2 Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Mon, 15 Jan 2024 16:14:14 +0000
Subject: [PATCH 05/18] fixup: return void in tests

---
 .../sme-inline-streaming-compatible-caller.c     |  6 ++----
 .../sme-inline-streaming-compatible.c            | 16 ++++++----------
 .../sme-inline-streaming-locally.c               | 10 ++++------
 .../sme-inline-streaming.c                       | 10 ++++------
 4 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
index 5c1779291a7e5b..add3f464bbaaa3 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
@@ -2,8 +2,6 @@
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
-int inlined_fn_streaming(void) __arm_streaming {
-    return 42;
-}
+void inlined_fn_streaming(void) __arm_streaming {}
 // expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
-int inlined_fn_caller(void) __arm_streaming_compatible { return inlined_fn_streaming(); }
+void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
index a996c429fdda0d..a07c42c141d5b2 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -2,16 +2,12 @@
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
-int inlined_fn_streaming_compatible(void) __arm_streaming_compatible {
-    return 42;
-}
+void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {}
 __attribute__((always_inline))
-int inlined_fn(void) {
-    return 42;
-}
-int inlined_fn_caller(void) { return inlined_fn_streaming_compatible(); }
+void inlined_fn(void) {}
+void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); }
 __arm_locally_streaming
-int inlined_fn_caller_local(void) { return inlined_fn_streaming_compatible(); }
-int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming_compatible(); }
+void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); }
+void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); }
 // expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}}
-int inlined_fn_caller_compatible(void) __arm_streaming_compatible { return inlined_fn(); }
+void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
index 4aa9fbf4a8fa18..6d645334ecb9d1 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
@@ -2,11 +2,9 @@
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline)) __arm_locally_streaming
-int inlined_fn_local(void) {
-    return 42;
-}
+void inlined_fn_local(void) {}
 // expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
-int inlined_fn_caller(void) { return inlined_fn_local(); }
+void inlined_fn_caller(void) { inlined_fn_local(); }
 __arm_locally_streaming
-int inlined_fn_caller_local(void) { return inlined_fn_local(); }
-int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_local(); }
+void inlined_fn_caller_local(void) { inlined_fn_local(); }
+void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
index 7268a49bb2491d..8afce84837838c 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
@@ -2,11 +2,9 @@
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
-int inlined_fn_streaming(void) __arm_streaming {
-    return 42;
-}
+void inlined_fn_streaming(void) __arm_streaming {}
 // expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
-int inlined_fn_caller(void) { return inlined_fn_streaming(); }
+void inlined_fn_caller(void) { inlined_fn_streaming(); }
 __arm_locally_streaming
-int inlined_fn_caller_local(void) { return inlined_fn_streaming(); }
-int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming(); }
+void inlined_fn_caller_local(void) { inlined_fn_streaming(); }
+void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); }

>From c49ff5e797a123a146c7df722556eb4d12c85047 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 17 Jan 2024 17:10:41 +0000
Subject: [PATCH 06/18] fixup: use SMEAttrs class

---
 clang/include/clang/Sema/Sema.h               |  8 ------
 clang/lib/CodeGen/CMakeLists.txt              |  2 +-
 clang/lib/CodeGen/Targets/AArch64.cpp         | 25 ++++++++++++-----
 clang/lib/Sema/SemaChecking.cpp               | 27 ++++++++++++-------
 .../llvm/Support}/AArch64SMEAttributes.h      |  0
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |  2 +-
 llvm/lib/Target/AArch64/SMEABIPass.cpp        |  2 +-
 .../AArch64/Utils/AArch64SMEAttributes.cpp    |  2 +-
 .../Target/AArch64/SMEAttributesTest.cpp      |  2 +-
 9 files changed, 40 insertions(+), 30 deletions(-)
 rename llvm/{lib/Target/AArch64/Utils => include/llvm/Support}/AArch64SMEAttributes.h (100%)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1ee065e7de9b15..6ce422d66ae5b0 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13832,16 +13832,8 @@ class Sema final {
     FormatArgumentPassingKind ArgPassingKind;
   };
 
-  enum ArmStreamingType {
-    ArmNonStreaming,
-    ArmStreaming,
-    ArmStreamingCompatible,
-    ArmStreamingOrSVE2p1
-  };
-
   static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
                                   bool IsVariadic, FormatStringInfo *FSI);
-  static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
 
 private:
   void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 03a6f2f1d7a9d2..919b826f5c5716 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -31,6 +31,7 @@ set(LLVM_LINK_COMPONENTS
   Target
   TargetParser
   TransformUtils
+  AArch64Utils
   )
 
 # Workaround for MSVC ARM64 performance regression:
@@ -151,5 +152,4 @@ add_clang_library(clangCodeGen
   clangFrontend
   clangLex
   clangSerialization
-  clangSema
   )
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 8d9f840c018fa5..8b15b798c5f896 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -9,7 +9,7 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Sema/Sema.h"
+#include "llvm/Support/AArch64SMEAttributes.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -827,13 +827,24 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   if (!Callee->hasAttr<AlwaysInlineAttr>())
     return;
 
-  auto CalleeStreamingMode = Sema::getArmStreamingFnType(Callee);
-  auto CallerStreamingMode = Sema::getArmStreamingFnType(Caller);
+  auto GetSMEAttrs = [](const FunctionDecl *F) {
+    llvm::SMEAttrs FAttrs;
+    if (F->hasAttr<ArmLocallyStreamingAttr>())
+      FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
+    if (const auto *T = F->getType()->getAs<FunctionProtoType>()) {
+      if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
+        FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
+      if (T->getAArch64SMEAttributes() &
+          FunctionType::SME_PStateSMCompatibleMask)
+        FAttrs.set(llvm::SMEAttrs::Mask::SM_Compatible);
+    }
+    return FAttrs;
+  };
+
+  auto CalleeAttrs = GetSMEAttrs(Callee);
+  auto CallerAttrs = GetSMEAttrs(Caller);
 
-  // The caller can inline the callee if their streaming modes match or the
-  // callee is streaming compatible
-  if (CalleeStreamingMode != CallerStreamingMode &&
-      CalleeStreamingMode != Sema::ArmStreamingCompatible)
+  if (CallerAttrs.requiresSMChange(CalleeAttrs, true))
     CGM.getDiags().Report(CallLoc,
                           diag::err_function_always_inline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a92db7d67e1cbd..ace3e386988f00 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2998,6 +2998,13 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
   llvm_unreachable("Invalid NeonTypeFlag!");
 }
 
+enum ArmStreamingType {
+  ArmNonStreaming,
+  ArmStreaming,
+  ArmStreamingCompatible,
+  ArmStreamingOrSVE2p1
+};
+
 bool Sema::ParseSVEImmChecks(
     CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
   // Perform all the immediate checks for this builtin call.
@@ -3138,7 +3145,7 @@ bool Sema::ParseSVEImmChecks(
   return HasError;
 }
 
-Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) {
+static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
   if (FD->hasAttr<ArmLocallyStreamingAttr>())
     return ArmStreaming;
   if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
@@ -3152,31 +3159,31 @@ Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) {
 
 static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
                                      const FunctionDecl *FD,
-                                     Sema::ArmStreamingType BuiltinType) {
-  Sema::ArmStreamingType FnType = Sema::getArmStreamingFnType(FD);
-  if (BuiltinType == Sema::ArmStreamingOrSVE2p1) {
+                                     ArmStreamingType BuiltinType) {
+  ArmStreamingType FnType = getArmStreamingFnType(FD);
+  if (BuiltinType == ArmStreamingOrSVE2p1) {
     // Check intrinsics that are available in [sve2p1 or sme/sme2].
     llvm::StringMap<bool> CallerFeatureMap;
     S.Context.getFunctionFeatureMap(CallerFeatureMap, FD);
     if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap))
-      BuiltinType = Sema::ArmStreamingCompatible;
+      BuiltinType = ArmStreamingCompatible;
     else
-      BuiltinType = Sema::ArmStreaming;
+      BuiltinType = ArmStreaming;
   }
 
-  if (FnType == Sema::ArmStreaming && BuiltinType == Sema::ArmNonStreaming) {
+  if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "streaming";
   }
 
-  if (FnType == Sema::ArmStreamingCompatible &&
-      BuiltinType != Sema::ArmStreamingCompatible) {
+  if (FnType == ArmStreamingCompatible &&
+      BuiltinType != ArmStreamingCompatible) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "streaming compatible";
     return;
   }
 
-  if (FnType == Sema::ArmNonStreaming && BuiltinType == Sema::ArmStreaming) {
+  if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) {
     S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
         << TheCall->getSourceRange() << "non-streaming";
   }
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h b/llvm/include/llvm/Support/AArch64SMEAttributes.h
similarity index 100%
rename from llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
rename to llvm/include/llvm/Support/AArch64SMEAttributes.h
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 6047a3b7b2864a..9d9d67490aa764 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -15,13 +15,13 @@
 #define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
 
 #include "AArch64.h"
-#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Instruction.h"
+#include "llvm/Support/AArch64SMEAttributes.h"
 
 namespace llvm {
 
diff --git a/llvm/lib/Target/AArch64/SMEABIPass.cpp b/llvm/lib/Target/AArch64/SMEABIPass.cpp
index 3315171798d9f1..b9a68179966c04 100644
--- a/llvm/lib/Target/AArch64/SMEABIPass.cpp
+++ b/llvm/lib/Target/AArch64/SMEABIPass.cpp
@@ -14,7 +14,6 @@
 
 #include "AArch64.h"
 #include "Utils/AArch64BaseInfo.h"
-#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/IRBuilder.h"
@@ -23,6 +22,7 @@
 #include "llvm/IR/IntrinsicsAArch64.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/Support/AArch64SMEAttributes.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
index ccdec78d780866..4af54c1d611d56 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "AArch64SMEAttributes.h"
+#include "llvm/Support/AArch64SMEAttributes.h"
 #include "llvm/IR/InstrTypes.h"
 #include <cassert>
 
diff --git a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
index 2f7201464ba2f2..b99cb4c0d775a8 100644
--- a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
+++ b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
@@ -1,7 +1,7 @@
-#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/AArch64SMEAttributes.h"
 #include "llvm/Support/SourceMgr.h"
 
 #include "gtest/gtest.h"

>From b38b7d59246de3a8a26e10238aed5cb757b89e1d Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Thu, 18 Jan 2024 11:07:00 +0000
Subject: [PATCH 07/18] fixup: rebase and check for new za state

---
 clang/include/clang/Basic/DiagnosticFrontendKinds.td       | 2 ++
 clang/lib/CodeGen/Targets/AArch64.cpp                      | 7 +++++++
 .../aarch64-sme-func-attrs-inline/sme-inline-new-za.c      | 6 ++++++
 3 files changed, 15 insertions(+)
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 27149553c79a2a..cbb5db3e0b1c82 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -281,6 +281,8 @@ def err_function_needs_feature : Error<
   "be inlined into function %0 that is compiled without support for '%2'">;
 def err_function_always_inline_attribute_mismatch : Error<
   "always_inline function %1 and its caller %0 have mismatched %2 attributes">;
+def err_function_always_inline_new_za : Error<
+  "always_inline function %0 has new za state">;
 
 def warn_avx_calling_convention
     : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' "
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 8b15b798c5f896..9f4323bef38896 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -831,6 +831,10 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
     llvm::SMEAttrs FAttrs;
     if (F->hasAttr<ArmLocallyStreamingAttr>())
       FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
+    if (auto *NewAttr = F->getAttr<ArmNewAttr>()) {
+      if (NewAttr->isNewZA())
+        FAttrs.set(llvm::SMEAttrs::Mask::ZA_New);
+    }
     if (const auto *T = F->getType()->getAs<FunctionProtoType>()) {
       if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
         FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
@@ -848,6 +852,9 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
     CGM.getDiags().Report(CallLoc,
                           diag::err_function_always_inline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
+  if (CalleeAttrs.hasNewZABody())
+    CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
+        << Callee->getDeclName();
 }
 
 std::unique_ptr<TargetCodeGenInfo>
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
new file mode 100644
index 00000000000000..97af6ec2be7a35
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
@@ -0,0 +1,6 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+__attribute__((always_inline)) __arm_new("za")
+void inline_new_za(void)  { }
+// expected-error at +1 {{always_inline function 'inline_new_za' has new za state}}
+void inline_caller() { inline_new_za(); }

>From c624882613fc3245ca3c8d73ce68b17a9cb43068 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Tue, 23 Jan 2024 14:43:32 +0000
Subject: [PATCH 08/18] fixup: re-implement SMEAttributes and check for lazy
 save

---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 +
 clang/lib/CodeGen/Targets/AArch64.cpp         | 81 +++++++++++++++----
 .../sme-inline-lazy-save.c                    | 14 ++++
 .../sme-inline-streaming-locally.c            |  4 +-
 .../sme-inline-streaming.c                    |  4 +-
 5 files changed, 86 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index cbb5db3e0b1c82..d31577b5cf5e74 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -283,6 +283,8 @@ def err_function_always_inline_attribute_mismatch : Error<
   "always_inline function %1 and its caller %0 have mismatched %2 attributes">;
 def err_function_always_inline_new_za : Error<
   "always_inline function %0 has new za state">;
+def err_function_always_inline_lazy_save : Error<
+  "inlining always_inline function %0 into %1 would require a lazy za save">;
 
 def warn_avx_calling_convention
     : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' "
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 9f4323bef38896..64d47a2f296d33 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -821,32 +821,80 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
                           /*allowHigherAlign*/ false);
 }
 
-void AArch64TargetCodeGenInfo::checkFunctionCallABI(
-    CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
-    const FunctionDecl *Callee, const CallArgList &Args) const {
-  if (!Callee->hasAttr<AlwaysInlineAttr>())
-    return;
+class SMEAttributes {
+public:
+  bool IsStreaming = false;
+  bool IsStreamingBody = false;
+  bool IsStreamingCompatible = false;
+  bool HasNewZA = false;
 
-  auto GetSMEAttrs = [](const FunctionDecl *F) {
-    llvm::SMEAttrs FAttrs;
+  SMEAttributes(const FunctionDecl *F) {
     if (F->hasAttr<ArmLocallyStreamingAttr>())
-      FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
+      IsStreamingBody = true;
     if (auto *NewAttr = F->getAttr<ArmNewAttr>()) {
       if (NewAttr->isNewZA())
-        FAttrs.set(llvm::SMEAttrs::Mask::ZA_New);
+        HasNewZA = true;
     }
     if (const auto *T = F->getType()->getAs<FunctionProtoType>()) {
       if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
-        FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled);
+        IsStreaming = true;
       if (T->getAArch64SMEAttributes() &
           FunctionType::SME_PStateSMCompatibleMask)
-        FAttrs.set(llvm::SMEAttrs::Mask::SM_Compatible);
+        IsStreamingCompatible = true;
+    }
+  }
+
+  bool hasStreamingBody() const { return IsStreamingBody; }
+  bool hasStreamingInterface() const { return IsStreaming; }
+  bool hasStreamingCompatibleInterface() const { return IsStreamingCompatible; }
+  bool hasStreamingInterfaceOrBody() const {
+    return hasStreamingBody() || hasStreamingInterface();
+  }
+  bool hasNonStreamingInterface() const {
+    return !hasStreamingInterface() && !hasStreamingCompatibleInterface();
+  }
+  bool hasNonStreamingInterfaceAndBody() const {
+    return hasNonStreamingInterface() && !hasStreamingBody();
+  }
+
+  bool requiresSMChange(const SMEAttributes Callee,
+                        bool BodyOverridesInterface = false) {
+    // If the transition is not through a call (e.g. when considering inlining)
+    // and Callee has a streaming body, then we can ignore the interface of
+    // Callee.
+    if (BodyOverridesInterface && Callee.hasStreamingBody()) {
+      return !hasStreamingInterfaceOrBody();
     }
-    return FAttrs;
-  };
 
-  auto CalleeAttrs = GetSMEAttrs(Callee);
-  auto CallerAttrs = GetSMEAttrs(Caller);
+    if (Callee.hasStreamingCompatibleInterface())
+      return false;
+
+    if (hasStreamingCompatibleInterface())
+      return true;
+
+    // Both non-streaming
+    if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
+      return false;
+
+    // Both streaming
+    if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
+      return false;
+
+    return Callee.hasStreamingInterface();
+  }
+
+  bool hasNewZABody() { return HasNewZA; }
+  bool requiresLazySave() const { return HasNewZA; }
+};
+
+void AArch64TargetCodeGenInfo::checkFunctionCallABI(
+    CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
+    const FunctionDecl *Callee, const CallArgList &Args) const {
+  if (!Callee->hasAttr<AlwaysInlineAttr>())
+    return;
+
+  SMEAttributes CalleeAttrs(Callee);
+  SMEAttributes CallerAttrs(Caller);
 
   if (CallerAttrs.requiresSMChange(CalleeAttrs, true))
     CGM.getDiags().Report(CallLoc,
@@ -855,6 +903,9 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   if (CalleeAttrs.hasNewZABody())
     CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
         << Callee->getDeclName();
+  if (CallerAttrs.requiresLazySave())
+    CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save)
+        << Callee->getDeclName() << Caller->getDeclName();
 }
 
 std::unique_ptr<TargetCodeGenInfo>
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c
new file mode 100644
index 00000000000000..4cd0b32a08dab0
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c
@@ -0,0 +1,14 @@
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+
+__attribute__((always_inline))
+void inlined(void) {}
+
+void inline_caller(void) {
+    inlined();
+}
+
+__arm_new("za")
+// expected-error at +2 {{inlining always_inline function 'inlined' into 'inline_caller_new_za' would require a lazy za save}}
+void inline_caller_new_za(void) {
+    inlined();
+}
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
index 6d645334ecb9d1..09bbbaf43ea5a2 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
@@ -3,8 +3,8 @@
 // Conflicting attributes when using always_inline
 __attribute__((always_inline)) __arm_locally_streaming
 void inlined_fn_local(void) {}
-// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
-void inlined_fn_caller(void) { inlined_fn_local(); }
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_local(); }
 void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); }
+// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+void inlined_fn_caller(void) { inlined_fn_local(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
index 8afce84837838c..9f0e944c8f8401 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
@@ -3,8 +3,8 @@
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
 void inlined_fn_streaming(void) __arm_streaming {}
-// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
-void inlined_fn_caller(void) { inlined_fn_streaming(); }
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_streaming(); }
 void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); }
+// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+void inlined_fn_caller(void) { inlined_fn_streaming(); }

>From 5d58e1e43da95aaa26aec1d43276d023cad7fac0 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Tue, 30 Jan 2024 11:33:17 +0000
Subject: [PATCH 09/18] fixup: simplify checking code

---
 clang/lib/CodeGen/Targets/AArch64.cpp | 53 +++------------------------
 1 file changed, 6 insertions(+), 47 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 64d47a2f296d33..e0efda49f5b549 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -824,13 +824,12 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
 class SMEAttributes {
 public:
   bool IsStreaming = false;
-  bool IsStreamingBody = false;
   bool IsStreamingCompatible = false;
   bool HasNewZA = false;
 
   SMEAttributes(const FunctionDecl *F) {
     if (F->hasAttr<ArmLocallyStreamingAttr>())
-      IsStreamingBody = true;
+      IsStreaming = true;
     if (auto *NewAttr = F->getAttr<ArmNewAttr>()) {
       if (NewAttr->isNewZA())
         HasNewZA = true;
@@ -843,48 +842,6 @@ class SMEAttributes {
         IsStreamingCompatible = true;
     }
   }
-
-  bool hasStreamingBody() const { return IsStreamingBody; }
-  bool hasStreamingInterface() const { return IsStreaming; }
-  bool hasStreamingCompatibleInterface() const { return IsStreamingCompatible; }
-  bool hasStreamingInterfaceOrBody() const {
-    return hasStreamingBody() || hasStreamingInterface();
-  }
-  bool hasNonStreamingInterface() const {
-    return !hasStreamingInterface() && !hasStreamingCompatibleInterface();
-  }
-  bool hasNonStreamingInterfaceAndBody() const {
-    return hasNonStreamingInterface() && !hasStreamingBody();
-  }
-
-  bool requiresSMChange(const SMEAttributes Callee,
-                        bool BodyOverridesInterface = false) {
-    // If the transition is not through a call (e.g. when considering inlining)
-    // and Callee has a streaming body, then we can ignore the interface of
-    // Callee.
-    if (BodyOverridesInterface && Callee.hasStreamingBody()) {
-      return !hasStreamingInterfaceOrBody();
-    }
-
-    if (Callee.hasStreamingCompatibleInterface())
-      return false;
-
-    if (hasStreamingCompatibleInterface())
-      return true;
-
-    // Both non-streaming
-    if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
-      return false;
-
-    // Both streaming
-    if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
-      return false;
-
-    return Callee.hasStreamingInterface();
-  }
-
-  bool hasNewZABody() { return HasNewZA; }
-  bool requiresLazySave() const { return HasNewZA; }
 };
 
 void AArch64TargetCodeGenInfo::checkFunctionCallABI(
@@ -896,14 +853,16 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   SMEAttributes CalleeAttrs(Callee);
   SMEAttributes CallerAttrs(Caller);
 
-  if (CallerAttrs.requiresSMChange(CalleeAttrs, true))
+  if (!CalleeAttrs.IsStreamingCompatible &&
+      (CallerAttrs.IsStreaming != CalleeAttrs.IsStreaming ||
+       CallerAttrs.IsStreamingCompatible))
     CGM.getDiags().Report(CallLoc,
                           diag::err_function_always_inline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
-  if (CalleeAttrs.hasNewZABody())
+  if (CalleeAttrs.HasNewZA)
     CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
         << Callee->getDeclName();
-  if (CallerAttrs.requiresLazySave())
+  if (CallerAttrs.HasNewZA)
     CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save)
         << Callee->getDeclName() << Caller->getDeclName();
 }

>From 626059f3edf7d271cfede424b4c787c8b6437087 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Tue, 30 Jan 2024 11:33:44 +0000
Subject: [PATCH 10/18] fixup: remove lazy save checking

---
 clang/lib/CodeGen/Targets/AArch64.cpp              |  3 ---
 .../sme-inline-lazy-save.c                         | 14 --------------
 2 files changed, 17 deletions(-)
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c

diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index e0efda49f5b549..c8b35a9d8c2b1a 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -862,9 +862,6 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
   if (CalleeAttrs.HasNewZA)
     CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
         << Callee->getDeclName();
-  if (CallerAttrs.HasNewZA)
-    CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save)
-        << Callee->getDeclName() << Caller->getDeclName();
 }
 
 std::unique_ptr<TargetCodeGenInfo>
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c
deleted file mode 100644
index 4cd0b32a08dab0..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
-
-__attribute__((always_inline))
-void inlined(void) {}
-
-void inline_caller(void) {
-    inlined();
-}
-
-__arm_new("za")
-// expected-error at +2 {{inlining always_inline function 'inlined' into 'inline_caller_new_za' would require a lazy za save}}
-void inline_caller_new_za(void) {
-    inlined();
-}

>From a5c1b77fab0b679ea373122f5fe1d4c378b8568b Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Tue, 30 Jan 2024 11:45:13 +0000
Subject: [PATCH 11/18] fixup: undo sme attrs header file move

---
 clang/lib/CodeGen/CMakeLists.txt                                | 1 -
 clang/lib/CodeGen/Targets/AArch64.cpp                           | 1 -
 llvm/lib/Target/AArch64/AArch64ISelLowering.h                   | 2 +-
 llvm/lib/Target/AArch64/SMEABIPass.cpp                          | 2 +-
 llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp          | 2 +-
 .../Support => lib/Target/AArch64/Utils}/AArch64SMEAttributes.h | 0
 llvm/unittests/Target/AArch64/SMEAttributesTest.cpp             | 2 +-
 7 files changed, 4 insertions(+), 6 deletions(-)
 rename llvm/{include/llvm/Support => lib/Target/AArch64/Utils}/AArch64SMEAttributes.h (100%)

diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 919b826f5c5716..52216d93a302bb 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -31,7 +31,6 @@ set(LLVM_LINK_COMPONENTS
   Target
   TargetParser
   TransformUtils
-  AArch64Utils
   )
 
 # Workaround for MSVC ARM64 performance regression:
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index c8b35a9d8c2b1a..df1c8fe25fbbd4 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -9,7 +9,6 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
-#include "llvm/Support/AArch64SMEAttributes.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 9d9d67490aa764..6047a3b7b2864a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -15,13 +15,13 @@
 #define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
 
 #include "AArch64.h"
+#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Instruction.h"
-#include "llvm/Support/AArch64SMEAttributes.h"
 
 namespace llvm {
 
diff --git a/llvm/lib/Target/AArch64/SMEABIPass.cpp b/llvm/lib/Target/AArch64/SMEABIPass.cpp
index b9a68179966c04..3315171798d9f1 100644
--- a/llvm/lib/Target/AArch64/SMEABIPass.cpp
+++ b/llvm/lib/Target/AArch64/SMEABIPass.cpp
@@ -14,6 +14,7 @@
 
 #include "AArch64.h"
 #include "Utils/AArch64BaseInfo.h"
+#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/IRBuilder.h"
@@ -22,7 +23,6 @@
 #include "llvm/IR/IntrinsicsAArch64.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/InitializePasses.h"
-#include "llvm/Support/AArch64SMEAttributes.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
index 4af54c1d611d56..ccdec78d780866 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/AArch64SMEAttributes.h"
+#include "AArch64SMEAttributes.h"
 #include "llvm/IR/InstrTypes.h"
 #include <cassert>
 
diff --git a/llvm/include/llvm/Support/AArch64SMEAttributes.h b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
similarity index 100%
rename from llvm/include/llvm/Support/AArch64SMEAttributes.h
rename to llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
diff --git a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
index b99cb4c0d775a8..2f7201464ba2f2 100644
--- a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
+++ b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
@@ -1,7 +1,7 @@
+#include "Utils/AArch64SMEAttributes.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
-#include "llvm/Support/AArch64SMEAttributes.h"
 #include "llvm/Support/SourceMgr.h"
 
 #include "gtest/gtest.h"

>From 30abfe2323705a7f5b9399da32f0df2c649f583f Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Tue, 30 Jan 2024 13:39:32 +0000
Subject: [PATCH 12/18] fixup: change error message

---
 clang/include/clang/Basic/DiagnosticFrontendKinds.td            | 2 +-
 .../sme-inline-streaming-compatible-caller.c                    | 2 +-
 .../sme-inline-streaming-compatible.c                           | 2 +-
 .../sme-inline-streaming-locally.c                              | 2 +-
 .../aarch64-sme-func-attrs-inline/sme-inline-streaming.c        | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index d31577b5cf5e74..f6e7bd72ac8448 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -280,7 +280,7 @@ def err_function_needs_feature : Error<
   "always_inline function %1 requires target feature '%2', but would "
   "be inlined into function %0 that is compiled without support for '%2'">;
 def err_function_always_inline_attribute_mismatch : Error<
-  "always_inline function %1 and its caller %0 have mismatched %2 attributes">;
+  "always_inline function %1 and its caller %0 have mismatching %2 attributes">;
 def err_function_always_inline_new_za : Error<
   "always_inline function %0 has new za state">;
 def err_function_always_inline_lazy_save : Error<
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
index add3f464bbaaa3..a52ae689b630a4 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
@@ -3,5 +3,5 @@
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
 void inlined_fn_streaming(void) __arm_streaming {}
-// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
 void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
index a07c42c141d5b2..2970f66b3905d8 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -9,5 +9,5 @@ void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); }
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); }
 void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); }
-// expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}}
+// expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatching streaming attributes}}
 void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
index 09bbbaf43ea5a2..f88564f2527a70 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
@@ -6,5 +6,5 @@ void inlined_fn_local(void) {}
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_local(); }
 void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); }
-// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
 void inlined_fn_caller(void) { inlined_fn_local(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
index 9f0e944c8f8401..480e99e313fe0b 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
@@ -6,5 +6,5 @@ void inlined_fn_streaming(void) __arm_streaming {}
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_streaming(); }
 void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); }
-// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
 void inlined_fn_caller(void) { inlined_fn_streaming(); }

>From 4c0341365d9e14165379f889f1882fe9d636cdaa Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 14 Feb 2024 13:31:02 +0000
Subject: [PATCH 13/18] fixup: remove lazy save error definition

---
 clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index f6e7bd72ac8448..1e1122f19c6178 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -283,8 +283,6 @@ def err_function_always_inline_attribute_mismatch : Error<
   "always_inline function %1 and its caller %0 have mismatching %2 attributes">;
 def err_function_always_inline_new_za : Error<
   "always_inline function %0 has new za state">;
-def err_function_always_inline_lazy_save : Error<
-  "inlining always_inline function %0 into %1 would require a lazy za save">;
 
 def warn_avx_calling_convention
     : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' "

>From c5dd67d9914a5eb80fe72dbf3e2acd8ec260e753 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 14 Feb 2024 13:31:14 +0000
Subject: [PATCH 14/18] fixup: remove attributes class

---
 clang/lib/CodeGen/Targets/AArch64.cpp | 56 ++++++++++++---------------
 1 file changed, 25 insertions(+), 31 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index df1c8fe25fbbd4..3ddea253daa72b 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -820,47 +820,41 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
                           /*allowHigherAlign*/ false);
 }
 
-class SMEAttributes {
-public:
-  bool IsStreaming = false;
-  bool IsStreamingCompatible = false;
-  bool HasNewZA = false;
-
-  SMEAttributes(const FunctionDecl *F) {
-    if (F->hasAttr<ArmLocallyStreamingAttr>())
-      IsStreaming = true;
-    if (auto *NewAttr = F->getAttr<ArmNewAttr>()) {
-      if (NewAttr->isNewZA())
-        HasNewZA = true;
-    }
-    if (const auto *T = F->getType()->getAs<FunctionProtoType>()) {
-      if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
-        IsStreaming = true;
-      if (T->getAArch64SMEAttributes() &
-          FunctionType::SME_PStateSMCompatibleMask)
-        IsStreamingCompatible = true;
-    }
-  }
-};
+static bool isStreaming(const FunctionDecl *F) {
+  if (F->hasAttr<ArmLocallyStreamingAttr>())
+    return true;
+  if (const auto *T = F->getType()->getAs<FunctionProtoType>())
+    return T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask;
+  return false;
+}
+
+static bool isStreamingCompatible(const FunctionDecl *F) {
+  if (const auto *T = F->getType()->getAs<FunctionProtoType>())
+    return T->getAArch64SMEAttributes() &
+           FunctionType::SME_PStateSMCompatibleMask;
+  return false;
+}
 
 void AArch64TargetCodeGenInfo::checkFunctionCallABI(
     CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
     const FunctionDecl *Callee, const CallArgList &Args) const {
-  if (!Callee->hasAttr<AlwaysInlineAttr>())
+  if (!Caller || !Callee->hasAttr<AlwaysInlineAttr>())
     return;
 
-  SMEAttributes CalleeAttrs(Callee);
-  SMEAttributes CallerAttrs(Caller);
+  bool CallerIsStreaming = isStreaming(Caller);
+  bool CalleeIsStreaming = isStreaming(Callee);
+  bool CallerIsStreamingCompatible = isStreamingCompatible(Caller);
+  bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee);
 
-  if (!CalleeAttrs.IsStreamingCompatible &&
-      (CallerAttrs.IsStreaming != CalleeAttrs.IsStreaming ||
-       CallerAttrs.IsStreamingCompatible))
+  if (!CalleeIsStreamingCompatible &&
+      (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible))
     CGM.getDiags().Report(CallLoc,
                           diag::err_function_always_inline_attribute_mismatch)
         << Caller->getDeclName() << Callee->getDeclName() << "streaming";
-  if (CalleeAttrs.HasNewZA)
-    CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
-        << Callee->getDeclName();
+  if (auto *NewAttr = Callee->getAttr<ArmNewAttr>())
+    if (NewAttr->isNewZA())
+      CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
+          << Callee->getDeclName();
 }
 
 std::unique_ptr<TargetCodeGenInfo>

>From e2fc441f9f9c7731f838fab004c64e2356bd1f4b Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 14 Feb 2024 13:35:27 +0000
Subject: [PATCH 15/18] fixup: define __ai in streaming compatible test

---
 .../sme-inline-streaming-compatible.c                      | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
index 2970f66b3905d8..1bc26f8ec7a55b 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -1,10 +1,9 @@
 // RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
 
 // Conflicting attributes when using always_inline
-__attribute__((always_inline))
-void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {}
-__attribute__((always_inline))
-void inlined_fn(void) {}
+#define __ai __attribute__((always_inline))
+__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {}
+__ai void inlined_fn(void) {}
 void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); }
 __arm_locally_streaming
 void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); }

>From 36a1a4331d37842ea14f094c51bb1a379f2b1f28 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 14 Feb 2024 13:36:54 +0000
Subject: [PATCH 16/18] fixup: remove -O3 from tests

---
 .../CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c   | 2 +-
 .../sme-inline-streaming-compatible-caller.c                    | 2 +-
 .../sme-inline-streaming-compatible.c                           | 2 +-
 .../sme-inline-streaming-locally.c                              | 2 +-
 .../aarch64-sme-func-attrs-inline/sme-inline-streaming.c        | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
index 97af6ec2be7a35..9d0423cb52e530 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
@@ -1,4 +1,4 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
 
 __attribute__((always_inline)) __arm_new("za")
 void inline_new_za(void)  { }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
index a52ae689b630a4..2ed48e86b481f1 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
@@ -1,4 +1,4 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
index 1bc26f8ec7a55b..b9a74fcfed103d 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -1,4 +1,4 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
 
 // Conflicting attributes when using always_inline
 #define __ai __attribute__((always_inline))
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
index f88564f2527a70..93f51af8211726 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
@@ -1,4 +1,4 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline)) __arm_locally_streaming
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
index 480e99e313fe0b..e024d697faf38c 100644
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
@@ -1,4 +1,4 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s
+// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
 
 // Conflicting attributes when using always_inline
 __attribute__((always_inline))

>From 3283c2e2e9264f5d8fbad79be86104897bd84d1a Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 14 Feb 2024 16:43:26 +0000
Subject: [PATCH 17/18] fixup: merge tests

---
 .../sme-inline-new-za.c                       |  6 ---
 .../sme-inline-streaming-compatible-caller.c  |  7 ---
 .../sme-inline-streaming-compatible.c         | 12 -----
 .../sme-inline-streaming-locally.c            | 10 ----
 .../sme-inline-streaming.c                    | 10 ----
 .../aarch64-sme-inline-streaming-attrs.c      | 47 +++++++++++++++++++
 6 files changed, 47 insertions(+), 45 deletions(-)
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
 delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
 create mode 100644 clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c

diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
deleted file mode 100644
index 9d0423cb52e530..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
-
-__attribute__((always_inline)) __arm_new("za")
-void inline_new_za(void)  { }
-// expected-error at +1 {{always_inline function 'inline_new_za' has new za state}}
-void inline_caller() { inline_new_za(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
deleted file mode 100644
index 2ed48e86b481f1..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
-
-// Conflicting attributes when using always_inline
-__attribute__((always_inline))
-void inlined_fn_streaming(void) __arm_streaming {}
-// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
-void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
deleted file mode 100644
index b9a74fcfed103d..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
-
-// Conflicting attributes when using always_inline
-#define __ai __attribute__((always_inline))
-__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {}
-__ai void inlined_fn(void) {}
-void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); }
-__arm_locally_streaming
-void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); }
-void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); }
-// expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatching streaming attributes}}
-void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
deleted file mode 100644
index 93f51af8211726..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
-
-// Conflicting attributes when using always_inline
-__attribute__((always_inline)) __arm_locally_streaming
-void inlined_fn_local(void) {}
-__arm_locally_streaming
-void inlined_fn_caller_local(void) { inlined_fn_local(); }
-void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); }
-// expected-error at +1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
-void inlined_fn_caller(void) { inlined_fn_local(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
deleted file mode 100644
index e024d697faf38c..00000000000000
--- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s
-
-// Conflicting attributes when using always_inline
-__attribute__((always_inline))
-void inlined_fn_streaming(void) __arm_streaming {}
-__arm_locally_streaming
-void inlined_fn_caller_local(void) { inlined_fn_streaming(); }
-void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); }
-// expected-error at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}}
-void inlined_fn_caller(void) { inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c
new file mode 100644
index 00000000000000..f653b512d14005
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE -x c %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE -x c %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING -x c %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY -x c %s
+
+#define __ai __attribute__((always_inline))
+__ai void inlined_fn(void) {}
+__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {}
+__ai void inlined_fn_streaming(void) __arm_streaming {}
+__ai __arm_locally_streaming void inlined_fn_local(void) {}
+
+#ifdef TEST_NONE
+void caller(void) {
+    inlined_fn();
+    inlined_fn_streaming_compatible();
+    inlined_fn_streaming(); // expected-error {{always_inline function 'inlined_fn_streaming' and its caller 'caller' have mismatching streaming attributes}}
+    inlined_fn_local(); // expected-error {{always_inline function 'inlined_fn_local' and its caller 'caller' have mismatching streaming attributes}}
+}
+#endif
+
+#ifdef TEST_COMPATIBLE
+void caller_compatible(void) __arm_streaming_compatible {
+    inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_compatible' have mismatching streaming attributes}}
+    inlined_fn_streaming_compatible();
+    inlined_fn_streaming(); // expected-error {{always_inline function 'inlined_fn_streaming' and its caller 'caller_compatible' have mismatching streaming attributes}}
+    inlined_fn_local(); // expected-error {{always_inline function 'inlined_fn_local' and its caller 'caller_compatible' have mismatching streaming attributes}}
+}
+#endif
+
+#ifdef TEST_STREAMING
+void caller_streaming(void) __arm_streaming {
+    inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_streaming' have mismatching streaming attributes}}
+    inlined_fn_streaming_compatible();
+    inlined_fn_streaming();
+    inlined_fn_local();
+}
+#endif
+
+#ifdef TEST_LOCALLY
+__arm_locally_streaming
+void caller_local(void) {
+    inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_local' have mismatching streaming attributes}}
+    inlined_fn_streaming_compatible();
+    inlined_fn_streaming();
+    inlined_fn_local();
+}
+#endif

>From e330889a7709c7323cc03d147156fd105174855c Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 21 Feb 2024 15:45:07 +0000
Subject: [PATCH 18/18] fixup: remove -x c and add Callee check

---
 clang/lib/CodeGen/Targets/AArch64.cpp                   | 2 +-
 clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 3ddea253daa72b..94f8e7be2ee6eb 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -838,7 +838,7 @@ static bool isStreamingCompatible(const FunctionDecl *F) {
 void AArch64TargetCodeGenInfo::checkFunctionCallABI(
     CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
     const FunctionDecl *Callee, const CallArgList &Args) const {
-  if (!Caller || !Callee->hasAttr<AlwaysInlineAttr>())
+  if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>())
     return;
 
   bool CallerIsStreaming = isStreaming(Caller);
diff --git a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c
index f653b512d14005..7eb74f28a1c85a 100644
--- a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c
+++ b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE -x c %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE -x c %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING -x c %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY -x c %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY %s
 
 #define __ai __attribute__((always_inline))
 __ai void inlined_fn(void) {}



More information about the cfe-commits mailing list