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

Sam Tebbs via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 18 01:56:01 PST 2024


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

>From bbc6c11cd3def5acbb2ba2f2ddc45df2c399f9d6 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 1/6] [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 568000106a84dc..dbd92b600a936e 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 4c464a1ae4c67f..0fed60103c9a2c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13803,8 +13803,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 7102d190fe008b..ea3d5a97605f1c 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;
@@ -153,6 +155,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 {
@@ -812,6 +819,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 74f8f626fb1637..160637dde448e4 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 0000293eac8600b97d2ca7374dda318eff1e7729 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 2/6] 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 0fed60103c9a2c..2ff1fcb01c91d8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13803,13 +13803,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 ea3d5a97605f1c..43555f577f0f50 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -822,14 +822,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 edff82e0f24a568c6041b648aec5c6bb85ac1318 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 3/6] 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 43555f577f0f50..7d944468d4dd49 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -825,12 +825,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 9b06764b5cfb6dc7cc7b2649bddafdde7029b342 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 4/6] 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 dbd92b600a936e..0d783c36e6ad2d 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 7d944468d4dd49..ec4c522ff4e527 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -833,7 +833,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 000833ae5e39144749a8b29c203a5ca50a3120fd 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 5/6] 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 90a6654023f63c511ab9e6711e039bf938d57841 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 6/6] 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 2ff1fcb01c91d8..4c464a1ae4c67f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13803,16 +13803,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 ec4c522ff4e527..87b8f737bee0e9 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;
@@ -825,13 +825,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 160637dde448e4..74f8f626fb1637 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 6ddbcd41dcb769..c7d5ac2ef2fc35 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 0082b4017986c6..4bc1ea3a1380fb 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 7780c71bbc00e0..c2fbccb14ef42c 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"



More information about the llvm-commits mailing list