[clang] [llvm] [ARM][AArch64] BTI, GCS, PAC Module flag update. (PR #86212)

Daniel Kiss via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 13:37:26 PDT 2024


https://github.com/DanielKristofKiss updated https://github.com/llvm/llvm-project/pull/86212

>From f2f3356da08d68dab4431f49d0921515560e4927 Mon Sep 17 00:00:00 2001
From: Daniel Kiss <daniel.kiss at arm.com>
Date: Fri, 8 Mar 2024 15:06:28 +0100
Subject: [PATCH 1/2] BTI,GCS,PAC Module flag update.

Module flag is used to indicate the feature to be propagated to the
function. As now the frontend emits all attributes accoringly let's
help the automerger to only do work when old and new bitcodes are
merged.
Autoupgrade function attributes from Module attributes when needed.
---
 clang/lib/CodeGen/CodeGenModule.cpp           |  19 ++--
 .../CodeGen/aarch64-sign-return-address.c     |  12 +--
 .../CodeGen/arm-branch-protection-attr-2.c    |   8 +-
 .../arm-ignore-branch-protection-option.c     |   2 +-
 llvm/include/llvm/IR/AutoUpgrade.h            |   3 +
 llvm/lib/AsmParser/LLParser.cpp               |   1 +
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     |   2 +
 llvm/lib/IR/AutoUpgrade.cpp                   | 100 +++++++++++++++++
 llvm/lib/Linker/IRMover.cpp                   |  10 ++
 llvm/lib/Target/ARM/ARMAsmPrinter.cpp         |   2 +-
 llvm/lib/Transforms/IPO/LowerTypeTests.cpp    |   2 +-
 .../test/Bitcode/upgrade-branch-protection.ll |  15 +--
 .../CodeGen/Thumb2/pacbti-m-outliner-5.ll     |   2 +-
 llvm/test/LTO/AArch64/Inputs/foo.ll           |  16 ---
 llvm/test/LTO/AArch64/TestInputs/bar.ll       |  35 ++++++
 llvm/test/LTO/AArch64/TestInputs/foo.ll       |  38 +++++++
 llvm/test/LTO/AArch64/TestInputs/old.ll       |  46 ++++++++
 .../AArch64/link-branch-target-enforcement.ll |   5 +-
 .../LTO/AArch64/link-sign-return-address.ll   | 102 ++++++++++++++++++
 llvm/test/Linker/link-arm-and-thumb.ll        |   6 +-
 llvm/test/ThinLTO/AArch64/aarch64_inline.ll   |  86 +++++++++++++++
 llvm/test/ThinLTO/AArch64/lit.local.cfg       |   2 +
 22 files changed, 468 insertions(+), 46 deletions(-)
 delete mode 100644 llvm/test/LTO/AArch64/Inputs/foo.ll
 create mode 100644 llvm/test/LTO/AArch64/TestInputs/bar.ll
 create mode 100644 llvm/test/LTO/AArch64/TestInputs/foo.ll
 create mode 100644 llvm/test/LTO/AArch64/TestInputs/old.ll
 create mode 100644 llvm/test/LTO/AArch64/link-sign-return-address.ll
 create mode 100644 llvm/test/ThinLTO/AArch64/aarch64_inline.ll
 create mode 100644 llvm/test/ThinLTO/AArch64/lit.local.cfg

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 227813ad44e8b8..6efc2283535f3a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1176,22 +1176,29 @@ void CodeGenModule::Release() {
                               "tag-stack-memory-buildattr", 1);
 
   if (T.isARM() || T.isThumb() || T.isAArch64()) {
+    // Previously 1 is used and meant for the backed to derive the function
+    // attribute form it. 2 now means function attributes already set for all
+    // functions in this module, so no need to propagate those from the module
+    // flag. Value is only used in case of LTO module merge because the backend
+    // will see all required function attribute set already. Value is used
+    // before modules got merged. Any posive value means the feature is active
+    // and required binary markings need to be emit accordingly.
     if (LangOpts.BranchTargetEnforcement)
       getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
-                                1);
+                                2);
     if (LangOpts.BranchProtectionPAuthLR)
       getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr",
-                                1);
+                                2);
     if (LangOpts.GuardedControlStack)
-      getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 1);
+      getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 2);
     if (LangOpts.hasSignReturnAddress())
-      getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1);
+      getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 2);
     if (LangOpts.isSignReturnAddressScopeAll())
       getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all",
-                                1);
+                                2);
     if (!LangOpts.isSignReturnAddressWithAKey())
       getModule().addModuleFlag(llvm::Module::Min,
-                                "sign-return-address-with-bkey", 1);
+                                "sign-return-address-with-bkey", 2);
 
     if (getTriple().isOSLinux()) {
       assert(getTriple().isOSBinFormatELF());
diff --git a/clang/test/CodeGen/aarch64-sign-return-address.c b/clang/test/CodeGen/aarch64-sign-return-address.c
index 8bc54b1a56c38c..35c56889e07071 100644
--- a/clang/test/CodeGen/aarch64-sign-return-address.c
+++ b/clang/test/CodeGen/aarch64-sign-return-address.c
@@ -22,17 +22,17 @@
 // NONE-NOT:  !"branch-target-enforcement"
 // ALL-NOT:   !"branch-target-enforcement"
 // PART-NOT:  !"branch-target-enforcement"
-// BTE:       !{i32 8, !"branch-target-enforcement", i32 1}
+// BTE:       !{i32 8, !"branch-target-enforcement", i32 2}
 // B-KEY-NOT: !"branch-target-enforcement"
 
 // NONE-NOT:  !"sign-return-address"
-// ALL:   !{i32 8, !"sign-return-address", i32 1}
-// PART:  !{i32 8, !"sign-return-address", i32 1}
+// ALL:   !{i32 8, !"sign-return-address", i32 2}
+// PART:  !{i32 8, !"sign-return-address", i32 2}
 // BTE-NOT:   !"sign-return-address"
-// B-KEY: !{i32 8, !"sign-return-address", i32 1}
+// B-KEY: !{i32 8, !"sign-return-address", i32 2}
 
 // NONE-NOT:  !"sign-return-address-all"
-// ALL:   !{i32 8, !"sign-return-address-all", i32 1}
+// ALL:   !{i32 8, !"sign-return-address-all", i32 2}
 // PART-NOT:  !"sign-return-address-all"
 // BTE-NOT:   !"sign-return-address-all"
 // B-KEY-NOT: !"sign-return-address-all"
@@ -41,6 +41,6 @@
 // ALL-NOT:   !"sign-return-address-with-bkey"
 // PART-NOT:  !"sign-return-address-with-bkey"
 // BTE-NOT:   !"sign-return-address-with-bkey"
-// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 1}
+// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 2}
 
 void foo() {}
diff --git a/clang/test/CodeGen/arm-branch-protection-attr-2.c b/clang/test/CodeGen/arm-branch-protection-attr-2.c
index 1f3c00873043e8..741c0026c4d05c 100644
--- a/clang/test/CodeGen/arm-branch-protection-attr-2.c
+++ b/clang/test/CodeGen/arm-branch-protection-attr-2.c
@@ -18,16 +18,16 @@
 // NONE-NOT: !"branch-target-enforcement"
 // PART-NOT: !"branch-target-enforcement"
 // ALL-NOT:  !"branch-target-enforcement"
-// BTE:      !{i32 8, !"branch-target-enforcement", i32 1}
+// BTE:      !{i32 8, !"branch-target-enforcement", i32 2}
 
 // NONE-NOT: !"sign-return-address"
-// PART:     !{i32 8, !"sign-return-address", i32 1}
-// ALL:      !{i32 8, !"sign-return-address", i32 1}
+// PART:     !{i32 8, !"sign-return-address", i32 2}
+// ALL:      !{i32 8, !"sign-return-address", i32 2}
 // BTE-NOT:  !"sign-return-address"
 
 // NONE-NOT: !"sign-return-address-all", i32 0}
 // PART-NOT: !"sign-return-address-all", i32 0}
-// ALL:      !{i32 8, !"sign-return-address-all", i32 1}
+// ALL:      !{i32 8, !"sign-return-address-all", i32 2}
 // BTE-NOT:  !"sign-return-address-all", i32 0}
 
 void foo() {}
diff --git a/clang/test/Frontend/arm-ignore-branch-protection-option.c b/clang/test/Frontend/arm-ignore-branch-protection-option.c
index 99a2accef3ae2f..45bdb37f5ed1a3 100644
--- a/clang/test/Frontend/arm-ignore-branch-protection-option.c
+++ b/clang/test/Frontend/arm-ignore-branch-protection-option.c
@@ -15,4 +15,4 @@ __attribute__((target("arch=cortex-m0"))) void f() {}
 // CHECK-NOT:  attributes { {{.*}} "branch-target-enforcement"
 
 /// Check that there are branch protection module attributes despite the warning.
-// CHECK: !{i32 8, !"branch-target-enforcement", i32 1}
+// CHECK: !{i32 8, !"branch-target-enforcement", i32 2}
diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h
index 97c3e4d7589d7b..7ac2037b53b29f 100644
--- a/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/llvm/include/llvm/IR/AutoUpgrade.h
@@ -89,6 +89,9 @@ namespace llvm {
   /// info. Return true if module is modified.
   bool UpgradeDebugInfo(Module &M);
 
+  /// Copies module attributes to the functions in the module.
+  void CopyModuleAttrToFunctions(Module &M);
+
   /// Check whether a string looks like an old loop attachment tag.
   inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
     return Name.starts_with("llvm.vectorizer.");
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 2902bd9fe17c48..8c4db1b85c4648 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -438,6 +438,7 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
 
   UpgradeModuleFlags(*M);
   UpgradeSectionAttributes(*M);
+  CopyModuleAttrToFunctions(*M);
 
   if (!Slots)
     return false;
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index c9295344f8080f..181cc426901ec3 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -6986,6 +6986,8 @@ Error BitcodeReader::materializeModule() {
 
   UpgradeARCRuntime(*TheModule);
 
+  CopyModuleAttrToFunctions(*TheModule);
+
   return Error::success();
 }
 
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index a7ed2de6e8a5ff..29e231b329a7d5 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -5296,6 +5296,106 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
   }
 }
 
+// Check if the module attribute is present and set to one.
+static bool isModuleAttributeOne(Module &M, const StringRef &ModAttr) {
+  const auto *Attr =
+      mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr));
+  return Attr && Attr->isOne();
+}
+
+// Check if the module attribute is present and set to two.
+static bool isModuleAttributeTwo(Module &M, const StringRef &ModAttr) {
+  const auto *Attr =
+      mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr));
+  return Attr && Attr->getZExtValue() == 2;
+}
+
+// Check if the function attribute is not present and set it.
+static void SetFunctionAttrIfNotSet(Function &F, StringRef FnAttrName,
+                                    StringRef Value) {
+  if (!F.hasFnAttribute(FnAttrName))
+    F.addFnAttr(FnAttrName, Value);
+}
+
+// Check if the function attribute is not present and set it if needed.
+// If the attribute is "false" then removes it.
+// If the attribute is "true" resets it to a valueless attribute.
+static void ConvertFunctionAttr(Function &F, bool Set, StringRef FnAttrName) {
+  if (!F.hasFnAttribute(FnAttrName)) {
+    if (Set)
+      F.addFnAttr(FnAttrName);
+  } else {
+    auto A = F.getFnAttribute(FnAttrName);
+    if ("false" == A.getValueAsString())
+      F.removeFnAttr(FnAttrName);
+    else if ("true" == A.getValueAsString()) {
+      F.removeFnAttr(FnAttrName);
+      F.addFnAttr(FnAttrName);
+    }
+  }
+}
+
+void llvm::CopyModuleAttrToFunctions(Module &M) {
+  Triple T(M.getTargetTriple());
+  if (!T.isThumb() && !T.isARM() && !T.isAArch64())
+    return;
+
+  if (isModuleAttributeTwo(M, "branch-target-enforcement"))
+    return;
+  if (isModuleAttributeTwo(M, "branch-protection-pauth-lr"))
+    return;
+  if (isModuleAttributeTwo(M, "guarded-control-stack"))
+    return;
+  if (isModuleAttributeTwo(M, "sign-return-address"))
+    return;
+
+  bool BTE = isModuleAttributeOne(M, "branch-target-enforcement");
+  bool BPPLR = isModuleAttributeOne(M, "branch-protection-pauth-lr");
+  bool GCS = isModuleAttributeOne(M, "guarded-control-stack");
+  bool SRA = isModuleAttributeOne(M, "sign-return-address");
+
+  StringRef SignTypeValue = "non-leaf";
+  if (SRA && isModuleAttributeOne(M, "sign-return-address-all"))
+    SignTypeValue = "all";
+
+  StringRef SignKeyValue = "a_key";
+  if (SRA && isModuleAttributeOne(M, "sign-return-address-with-bkey"))
+    SignKeyValue = "b_key";
+
+  for (Function &F : M.getFunctionList()) {
+    if (F.isDeclaration())
+      continue;
+
+    if (SRA) {
+      SetFunctionAttrIfNotSet(F, "sign-return-address", SignTypeValue);
+      SetFunctionAttrIfNotSet(F, "sign-return-address-key", SignKeyValue);
+    } else {
+      if (auto A = F.getFnAttribute("sign-return-address");
+          A.isValid() && "none" == A.getValueAsString()) {
+        F.removeFnAttr("sign-return-address");
+        F.removeFnAttr("sign-return-address-key");
+      }
+    }
+    ConvertFunctionAttr(F, BTE, "branch-target-enforcement");
+    ConvertFunctionAttr(F, BPPLR, "branch-protection-pauth-lr");
+    ConvertFunctionAttr(F, GCS, "guarded-control-stack");
+  }
+
+  if (BTE)
+    M.setModuleFlag(llvm::Module::Min, "branch-target-enforcement", 2);
+  if (BPPLR)
+    M.setModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr", 2);
+  if (GCS)
+    M.setModuleFlag(llvm::Module::Min, "guarded-control-stack", 2);
+  if (SRA) {
+    M.setModuleFlag(llvm::Module::Min, "sign-return-address", 2);
+    if (isModuleAttributeOne(M, "sign-return-address-all"))
+      M.setModuleFlag(llvm::Module::Min, "sign-return-address-all", 2);
+    if (isModuleAttributeOne(M, "sign-return-address-with-bkey"))
+      M.setModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", 2);
+  }
+}
+
 static bool isOldLoopArgument(Metadata *MD) {
   auto *T = dyn_cast_or_null<MDTuple>(MD);
   if (!T)
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index 7a5aa0c8047821..3734563f7d697e 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -1608,6 +1608,11 @@ Error IRLinker::run() {
   // Loop over all of the linked values to compute type mappings.
   computeTypeMapping();
 
+  // Convert module level attributes to function level attributes because
+  // after merging modules the attributes might change and would have different
+  // effect on the functions as the original module would have.
+  CopyModuleAttrToFunctions(*SrcM);
+
   std::reverse(Worklist.begin(), Worklist.end());
   while (!Worklist.empty()) {
     GlobalValue *GV = Worklist.back();
@@ -1772,6 +1777,11 @@ IRMover::IRMover(Module &M) : Composite(M) {
   for (const auto *MD : StructTypes.getVisitedMetadata()) {
     SharedMDs[MD].reset(const_cast<MDNode *>(MD));
   }
+
+  // Convert module level attributes to function level attributes because
+  // after merging modules the attributes might change and would have different
+  // effect on the functions as the original module would have.
+  CopyModuleAttrToFunctions(M);
 }
 
 Error IRMover::move(std::unique_ptr<Module> Src,
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index 642739a29d6b06..fe9f207a53e436 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -793,7 +793,7 @@ void ARMAsmPrinter::emitAttributes() {
 
     auto *BTIValue = mdconst::extract_or_null<ConstantInt>(
         SourceModule->getModuleFlag("branch-target-enforcement"));
-    if (BTIValue && BTIValue->isOne()) {
+    if (BTIValue && !BTIValue->isZero()) {
       // If "+pacbti" is used as an architecture extension,
       // Tag_BTI_extension is emitted in
       // ARMTargetStreamer::emitTargetAttributes().
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index 633fcb3314c42f..943360f725ce1f 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -1211,7 +1211,7 @@ bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
     // the module flags.
     if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
           M.getModuleFlag("branch-target-enforcement")))
-      HasBranchTargetEnforcement = (BTE->getZExtValue() != 0);
+      HasBranchTargetEnforcement = !BTE->isZero();
     else
       HasBranchTargetEnforcement = 0;
   }
diff --git a/llvm/test/Bitcode/upgrade-branch-protection.ll b/llvm/test/Bitcode/upgrade-branch-protection.ll
index 1b33e3901198ea..6f60ba543e6c04 100644
--- a/llvm/test/Bitcode/upgrade-branch-protection.ll
+++ b/llvm/test/Bitcode/upgrade-branch-protection.ll
@@ -1,8 +1,11 @@
-;; Test that module flags "branch-target-enforcement" and "sign-return-address"  can be upgraded to
-;; are upgraded from Error to Min.
+;; Test that module flags "branch-target-enforcement" and "sign-return-address"
+;; can be upgraded to are upgraded from Error to Min and the value is changed 2
+;; as the module is converted to the semantic.
 
 ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s
 
+target triple = "aarch64-unknown-linux-gnu"
+
 !llvm.module.flags = !{!0, !1, !2, !3}
 
 !0 = !{i32 1, !"branch-target-enforcement", i32 1}
@@ -10,7 +13,7 @@
 !2 = !{i32 1, !"sign-return-address-all", i32 1}
 !3 = !{i32 1, !"sign-return-address-with-bkey", i32 1}
 
-;CHECK: !0 = !{i32 8, !"branch-target-enforcement", i32 1}
-;CHECK: !1 = !{i32 8, !"sign-return-address", i32 1}
-;CHECK: !2 = !{i32 8, !"sign-return-address-all", i32 1}
-;CHECK: !3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
\ No newline at end of file
+;CHECK: !0 = !{i32 8, !"branch-target-enforcement", i32 2}
+;CHECK: !1 = !{i32 8, !"sign-return-address", i32 2}
+;CHECK: !2 = !{i32 8, !"sign-return-address-all", i32 2}
+;CHECK: !3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
diff --git a/llvm/test/CodeGen/Thumb2/pacbti-m-outliner-5.ll b/llvm/test/CodeGen/Thumb2/pacbti-m-outliner-5.ll
index 6bfaf3bb520a0a..77c3424f4abf30 100644
--- a/llvm/test/CodeGen/Thumb2/pacbti-m-outliner-5.ll
+++ b/llvm/test/CodeGen/Thumb2/pacbti-m-outliner-5.ll
@@ -94,5 +94,5 @@ attributes #1 = { minsize nofree norecurse nounwind optsize "sign-return-address
 !llvm.module.flags = !{!0, !1, !2}
 
 !0 = !{i32 8, !"branch-target-enforcement", i32 0}
-!1 = !{i32 8, !"sign-return-address", i32 1}
+!1 = !{i32 8, !"sign-return-address", i32 2}
 !2 = !{i32 8, !"sign-return-address-all", i32 0}
diff --git a/llvm/test/LTO/AArch64/Inputs/foo.ll b/llvm/test/LTO/AArch64/Inputs/foo.ll
deleted file mode 100644
index 961b0d4e7997e1..00000000000000
--- a/llvm/test/LTO/AArch64/Inputs/foo.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
-target triple = "aarch64-unknown-linux-gnu"
-
-define dso_local i32 @foo() #0 {
-entry:
-  ret i32 42
-}
-
-attributes #0 = { noinline nounwind optnone uwtable }
-
-!llvm.module.flags = !{!0, !1, !2, !3}
-
-!0 = !{i32 8, !"branch-target-enforcement", i32 1}
-!1 = !{i32 8, !"sign-return-address", i32 1}
-!2 = !{i32 8, !"sign-return-address-all", i32 1}
-!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
diff --git a/llvm/test/LTO/AArch64/TestInputs/bar.ll b/llvm/test/LTO/AArch64/TestInputs/bar.ll
new file mode 100644
index 00000000000000..e8a92767c8d7a3
--- /dev/null
+++ b/llvm/test/LTO/AArch64/TestInputs/bar.ll
@@ -0,0 +1,35 @@
+; This file contains the new semantic of the branch-target-enforcement, sign-return-address.
+; Used for test mixing a mixed link case and also verify the import too in llc.
+
+; RUN: llc %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define dso_local void @bar() #0 {
+entry:
+  ret void
+}
+; CHECK-LABEL: bar:
+; CHECK-NOT:       hint
+; CHECK-NOT:       bti
+; CHECK:           ret
+
+define dso_local void @baz() #1 {
+entry:
+  ret void
+}
+
+; CHECK-LABEL: baz:
+; CHECK:           hint
+; CHECK:           ret
+
+attributes #0 = { noinline nounwind optnone uwtable }
+attributes #1 = { noinline nounwind optnone uwtable "branch-target-enforcement" }
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 8, !"branch-target-enforcement", i32 2}
+!1 = !{i32 8, !"sign-return-address", i32 2}
+!2 = !{i32 8, !"sign-return-address-all", i32 2}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
diff --git a/llvm/test/LTO/AArch64/TestInputs/foo.ll b/llvm/test/LTO/AArch64/TestInputs/foo.ll
new file mode 100644
index 00000000000000..7a4cb2ce5ade78
--- /dev/null
+++ b/llvm/test/LTO/AArch64/TestInputs/foo.ll
@@ -0,0 +1,38 @@
+; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
+; Used for test mixing a mixed link case and also verify the import too in llc.
+
+; RUN: llc %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define i32 @foo() #0 {
+entry:
+  ret i32 42
+}
+
+; CHECK-LABEL: foo:
+; CHECK:           hint    #27
+; CHECK:           mov
+; CHECK:           hint    #31
+; CHECK:           ret
+
+define i32 @fiz() #1 {
+entry:
+  ret i32 43
+}
+
+; CHECK-LABEL: fiz:
+; CHECK-NOT:       hint
+; CHECK-NOT:       bti
+; CHECK:           ret
+
+attributes #0 = { noinline nounwind optnone uwtable }
+attributes #1 = { noinline nounwind optnone uwtable "branch-target-enforcement"="false" "sign-return-address"="none" }
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 8, !"branch-target-enforcement", i32 1}
+!1 = !{i32 8, !"sign-return-address", i32 1}
+!2 = !{i32 8, !"sign-return-address-all", i32 1}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
diff --git a/llvm/test/LTO/AArch64/TestInputs/old.ll b/llvm/test/LTO/AArch64/TestInputs/old.ll
new file mode 100644
index 00000000000000..119ea6fabbd70a
--- /dev/null
+++ b/llvm/test/LTO/AArch64/TestInputs/old.ll
@@ -0,0 +1,46 @@
+; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
+; Used for test mixing a mixed link case and also verify the import too in llc.
+
+; RUN: llc %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define i32 @old_bti() #0 {
+entry:
+  ret i32 2
+}
+
+; CHECK-LABEL: old_bti:
+; CHECK:           hint    #34
+; CHECK:           mov
+; CHECK:           ret
+
+define i32 @old_pac() #1 {
+entry:
+  ret i32 2
+}
+
+; CHECK-LABEL: old_pac:
+; CHECK:           hint    #25
+; CHECK:           hint    #29
+; CHECK:           ret
+
+
+define i32 @old_none() #2 {
+entry:
+  ret i32 3
+}
+
+; CHECK-LABEL: old_none:
+; CHECK-NOT:           hint
+; CHECK-NOT:           paci
+; CHECK-NOT:           bti
+; CHECK:           ret
+
+
+attributes #0 = { noinline nounwind optnone "branch-target-enforcement"="true" }
+attributes #1 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="all" }
+attributes #2 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="none" }
+
+; Intentionally no module flags
diff --git a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
index ccf8cf67ede6dc..4c6e4dbb64e63c 100644
--- a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
+++ b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
@@ -2,7 +2,7 @@
 ; be mixed.
 ;
 ; RUN: llvm-as %s -o %t1.bc
-; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc
+; RUN: llvm-as %p/TestInputs/foo.ll -o %t2.bc
 ; RUN: llvm-lto -exported-symbol main \
 ; RUN:          -exported-symbol foo \
 ; RUN:          -filetype=obj \
@@ -30,8 +30,11 @@ entry:
 
 ; CHECK-NOT: linking module flags 'branch-target-enforcement': IDs have conflicting values in
 ; CHECK-DUMP: <main>:
+; CHECK-DUMP:      paciasp
+; CHECK-DUMP:      str
 ; CHECK-DUMP:      bl      0x8 <main+0x8>
 ; CHECK-DUMP: <foo>:
+; CHECK-DUMP:     pacibsp
 
 ; `main` doesn't support BTI while `foo` does, so in the binary
 ; we should see only PAC which is supported by both.
diff --git a/llvm/test/LTO/AArch64/link-sign-return-address.ll b/llvm/test/LTO/AArch64/link-sign-return-address.ll
new file mode 100644
index 00000000000000..84b4aff10f8c48
--- /dev/null
+++ b/llvm/test/LTO/AArch64/link-sign-return-address.ll
@@ -0,0 +1,102 @@
+; Testcase to check that module with different sign return address can
+; be mixed.
+;
+; RUN: llvm-as %s -o %t1.bc
+; RUN: llvm-as %p/TestInputs/foo.ll -o %t2.bc
+; RUN: llvm-as %p/TestInputs/bar.ll -o %t3.bc
+; RUN: llvm-as %p/TestInputs/old.ll -o %t4.bc
+; RUN: llvm-lto -exported-symbol main \
+; RUN:          -exported-symbol foo \
+; RUN:          -exported-symbol fiz \
+; RUN:          -exported-symbol bar \
+; RUN:          -exported-symbol baz \
+; RUN:          -exported-symbol old_bti \
+; RUN:          -exported-symbol old_pac \
+; RUN:          -exported-symbol old_none \
+; RUN:          -filetype=obj \
+; RUN:          %t4.bc %t3.bc %t2.bc %t1.bc \
+; RUN:           -o %t1.exe 2>&1
+; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
+; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+declare i32 @foo();
+declare i32 @fiz();
+declare void @baz();
+declare void @bar();
+declare i32 @old_bti();
+declare i32 @old_pac();
+declare i32 @old_none();
+
+define i32 @main() #0 {
+entry:
+  call i32 @foo()
+  call i32 @fiz()
+  call void @bar()
+  call void @baz()
+  call i32 @old_bti()
+  call i32 @old_pac()
+  call i32 @old_none()
+  ret i32 0
+}
+
+attributes #0 = { noinline nounwind optnone }
+
+!llvm.module.flags = !{!0, !1, !2, !3 }
+!0 = !{i32 8, !"branch-target-enforcement", i32 0}
+!1 = !{i32 8, !"sign-return-address", i32 0}
+!2 = !{i32 8, !"sign-return-address-all", i32 0}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
+
+
+; CHECK-DUMP-LABEL: <old_bti>:
+; CHECK-DUMP-NEXT:     bti c
+; CHECK-DUMP-NEXT:     mov     w0, #0x2
+; CHECK-DUMP-NEXT:     ret
+
+; CHECK-DUMP-LABEL: <old_pac>:
+; CHECK-DUMP-NEXT:     paciasp
+; CHECK-DUMP-NEXT:     mov     w0, #0x2
+; CHECK-DUMP-NEXT:     autiasp
+; CHECK-DUMP-NEXT:     ret
+
+; CHECK-DUMP-LABEL: <old_none>:
+; CHECK-DUMP-NEXT:     mov     w0, #0x3
+; CHECK-DUMP-NEXT:     ret
+
+; CHECK-DUMP-LABEL: <bar>:
+; CHECK-DUMP-NEXT:     ret
+
+; CHECK-DUMP-LABEL: <baz>:
+; CHECK-DUMP-NEXT:     bti     c
+; CHECK-DUMP-NEXT:     ret
+
+; foo.ll represents a module with the old style of the function attributes.
+; foo shall have PAC with B-key as it requested at module level.
+; CHECK-DUMP-LABEL: <foo>:
+; CHECK-DUMP-NEXT:     pacibsp
+; CHECK-DUMP-NEXT:     mov     w0, #0x2a
+; CHECK-DUMP-NEXT:     autibsp
+; CHECK-DUMP-NEXT:     ret
+
+; fiz shall not have BTI or PAC instructions as they are disabled at function scope.
+; CHECK-DUMP-LABEL:  <fiz>:
+; CHECK-DUMP-NEXT:       mov     w0, #0x2b
+; CHECK-DUMP-NEXT:       ret
+
+; CHECK-DUMP-LABEL: <main>:
+; CHECK-DUMP-NOT:       paciasp
+; CHECK-DUMP-NEXT:      str     x30,
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+
+; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
+; we should not see anything.
+; CHECK-PROP-NOT:   Properties: aarch64 feature: PAC
diff --git a/llvm/test/Linker/link-arm-and-thumb.ll b/llvm/test/Linker/link-arm-and-thumb.ll
index a90f2128e4430a..b5984bf5579477 100644
--- a/llvm/test/Linker/link-arm-and-thumb.ll
+++ b/llvm/test/Linker/link-arm-and-thumb.ll
@@ -13,11 +13,11 @@ entry:
   ret i32 %add
 }
 
-; CHECK: define i32 @main() {
+; CHECK: define i32 @main()
 ; CHECK: define i32 @foo(i32 %a, i32 %b) [[ARM_ATTRS:#[0-9]+]]
 ; CHECK: define i32 @bar(i32 %a, i32 %b) [[THUMB_ATTRS:#[0-9]+]]
 
-; CHECK: attributes [[ARM_ATTRS]] = { "target-features"="-thumb-mode" }
-; CHECK: attributes [[THUMB_ATTRS]] = { "target-features"="+thumb-mode" }
+; CHECK: attributes [[ARM_ATTRS]] = {{{.*}}"target-features"="-thumb-mode" }
+; CHECK: attributes [[THUMB_ATTRS]] = {{{.*}}"target-features"="+thumb-mode" }
 
 ; STDERR-NOT: warning: Linking two modules of different target triples:
diff --git a/llvm/test/ThinLTO/AArch64/aarch64_inline.ll b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
new file mode 100644
index 00000000000000..3e286630a52959
--- /dev/null
+++ b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
@@ -0,0 +1,86 @@
+;; Test verifies inlining happens cross module when module flags are upgraded.
+;; `foo` and `main` are both old semantic while bar is the new semantic.
+;; Regression test for #82763
+
+; RUN: split-file %s %t
+; RUN: opt -module-summary %t/foo.s -o %t/foo.o
+; RUN: opt -module-summary %t/bar.s -o %t/bar.o
+; RUN: opt -module-summary %t/main.s -o %t/main.o
+; RUN: llvm-lto2 run %t/main.o %t/foo.o %t/bar.o -save-temps \
+; RUN:   -o %t/t.exe \
+; RUN:   -r=%t/foo.o,foo,plx \
+; RUN:   -r=%t/bar.o,bar,plx \
+; RUN:   -r=%t/main.o,foo,l \
+; RUN:   -r=%t/main.o,bar,l \
+; RUN:   -r=%t/main.o,main,plx 2>&1
+; RUN: llvm-dis %t/t.exe.1.4.opt.bc -o - | FileCheck %s
+
+; CHECK:      define dso_local noundef i32 @main() local_unnamed_addr #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:  ret i32 35
+; CHECK-NEXT: }
+
+; CHECK:  attributes #0 = { {{.*}}"branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="b_key" }
+
+; CHECK: !llvm.module.flags = !{!0, !1, !2, !3}
+
+; CHECK: !0 = !{i32 8, !"branch-target-enforcement", i32 2}
+; CHECK: !1 = !{i32 8, !"sign-return-address", i32 2}
+; CHECK: !2 = !{i32 8, !"sign-return-address-all", i32 2}
+; CHECK: !3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
+
+
+;--- foo.s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define dso_local noundef i32 @foo() local_unnamed_addr #0 {
+entry:
+  ret i32 34
+}
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
+!llvm.module.flags = !{!0, !1, !2, !3 }
+!0 = !{i32 8, !"branch-target-enforcement", i32 1}
+!1 = !{i32 8, !"sign-return-address", i32 1}
+!2 = !{i32 8, !"sign-return-address-all", i32 1}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
+
+;--- bar.s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define dso_local noundef i32 @bar() local_unnamed_addr #0 {
+entry:
+  ret i32 1
+}
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="b_key" }
+!llvm.module.flags = !{!0, !1, !2, !3 }
+!0 = !{i32 8, !"branch-target-enforcement", i32 2}
+!1 = !{i32 8, !"sign-return-address", i32 2}
+!2 = !{i32 8, !"sign-return-address-all", i32 2}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
+
+;--- main.s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+declare i32 @foo();
+declare i32 @bar();
+
+define i32 @main() #0 {
+entry:
+  %1 = call i32 @foo()
+  %2 = call i32 @bar()
+  %3 = add i32 %1, %2
+  ret i32 %3
+}
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
+
+!llvm.module.flags = !{!0, !1, !2, !3 }
+!0 = !{i32 8, !"branch-target-enforcement", i32 1}
+!1 = !{i32 8, !"sign-return-address", i32 1}
+!2 = !{i32 8, !"sign-return-address-all", i32 1}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
diff --git a/llvm/test/ThinLTO/AArch64/lit.local.cfg b/llvm/test/ThinLTO/AArch64/lit.local.cfg
new file mode 100644
index 00000000000000..10d4a0e953ed47
--- /dev/null
+++ b/llvm/test/ThinLTO/AArch64/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "AArch64" in config.root.targets:
+    config.unsupported = True

>From 99b6f2bc9c472fe930e216cf4cc72dd5cdbf14d7 Mon Sep 17 00:00:00 2001
From: Daniel Kiss <daniel.kiss at arm.com>
Date: Thu, 8 Aug 2024 22:19:12 +0200
Subject: [PATCH 2/2] address review comments

---
 llvm/include/llvm/IR/AutoUpgrade.h            |  7 +++
 llvm/test/LTO/AArch64/TestInputs/bar.ll       |  8 +--
 llvm/test/LTO/AArch64/TestInputs/fiz.ll       | 41 ++++++++++++
 llvm/test/LTO/AArch64/TestInputs/foo.ll       | 20 +++---
 llvm/test/LTO/AArch64/TestInputs/old.ll       | 31 ++++++---
 .../AArch64/link-branch-target-enforcement.ll | 18 +++---
 .../LTO/AArch64/link-sign-return-address.ll   | 63 +++++++++++++------
 llvm/test/ThinLTO/AArch64/aarch64_inline.ll   |  6 +-
 8 files changed, 140 insertions(+), 54 deletions(-)
 create mode 100644 llvm/test/LTO/AArch64/TestInputs/fiz.ll

diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h
index 7ac2037b53b29f..5d7b6f47ea3ffe 100644
--- a/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/llvm/include/llvm/IR/AutoUpgrade.h
@@ -90,6 +90,13 @@ namespace llvm {
   bool UpgradeDebugInfo(Module &M);
 
   /// Copies module attributes to the functions in the module.
+  /// Currently only effects ARM, Thumb and AArch64 targets.
+  /// Supported attributes:
+  ///  - branch-target-enforcement
+  ///  - branch-protection-pauth-lr
+  ///  - guarded-control-stack
+  ///  - sign-return-address
+  ///  - sign-return-address-with-bkey
   void CopyModuleAttrToFunctions(Module &M);
 
   /// Check whether a string looks like an old loop attachment tag.
diff --git a/llvm/test/LTO/AArch64/TestInputs/bar.ll b/llvm/test/LTO/AArch64/TestInputs/bar.ll
index e8a92767c8d7a3..7c2a753bcc403e 100644
--- a/llvm/test/LTO/AArch64/TestInputs/bar.ll
+++ b/llvm/test/LTO/AArch64/TestInputs/bar.ll
@@ -1,7 +1,7 @@
-; This file contains the new semantic of the branch-target-enforcement, sign-return-address.
-; Used for test mixing a mixed link case and also verify the import too in llc.
+;; This file contains the new semantic of the branch-target-enforcement, sign-return-address.
+;; Used for test mixing a mixed link case and also verify the import too in llc.
 
-; RUN: llc %s -o - | FileCheck %s
+; RUN: llc -mattr=+pauth -mattr=+bti %s -o - | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
@@ -21,7 +21,7 @@ entry:
 }
 
 ; CHECK-LABEL: baz:
-; CHECK:           hint
+; CHECK:           bti c
 ; CHECK:           ret
 
 attributes #0 = { noinline nounwind optnone uwtable }
diff --git a/llvm/test/LTO/AArch64/TestInputs/fiz.ll b/llvm/test/LTO/AArch64/TestInputs/fiz.ll
new file mode 100644
index 00000000000000..e57842681d9189
--- /dev/null
+++ b/llvm/test/LTO/AArch64/TestInputs/fiz.ll
@@ -0,0 +1,41 @@
+;; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
+;; Used for test mixing a mixed link case and also verify the import too in llc.
+
+; RUN: llc -mattr=+pauth -mattr=+bti %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+declare void @func()
+
+define i32 @fiz_on() #0 {
+entry:
+  call void @func()
+  ret i32 42
+}
+
+; CHECK-LABEL: fiz_on:
+; CHECK:           paciasp
+; CHECK:           bl func
+; CHECK:           retaa
+
+define i32 @fiz_off() #1 {
+entry:
+  ret i32 43
+}
+
+; CHECK-LABEL: fiz_off:
+; CHECK-NOT:       pac
+; CHECK-NOT:       hint
+; CHECK-NOT:       bti
+; CHECK:           ret
+
+attributes #0 = { noinline nounwind optnone uwtable }
+attributes #1 = { noinline nounwind optnone uwtable "branch-target-enforcement"="false" "sign-return-address"="none" }
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 8, !"branch-target-enforcement", i32 1}
+!1 = !{i32 8, !"sign-return-address", i32 1}
+!2 = !{i32 8, !"sign-return-address-all", i32 0}
+!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
diff --git a/llvm/test/LTO/AArch64/TestInputs/foo.ll b/llvm/test/LTO/AArch64/TestInputs/foo.ll
index 7a4cb2ce5ade78..689d93849939d4 100644
--- a/llvm/test/LTO/AArch64/TestInputs/foo.ll
+++ b/llvm/test/LTO/AArch64/TestInputs/foo.ll
@@ -1,28 +1,28 @@
-; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
-; Used for test mixing a mixed link case and also verify the import too in llc.
+;; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
+;; Used for test mixing a mixed link case and also verify the import too in llc.
 
-; RUN: llc %s -o - | FileCheck %s
+; RUN: llc -mattr=+pauth -mattr=+bti %s -o - | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
-define i32 @foo() #0 {
+define i32 @foo_on() #0 {
 entry:
   ret i32 42
 }
 
-; CHECK-LABEL: foo:
-; CHECK:           hint    #27
+; CHECK-LABEL: foo_on:
+; CHECK:           pacibsp
 ; CHECK:           mov
-; CHECK:           hint    #31
-; CHECK:           ret
+; CHECK:           retab
 
-define i32 @fiz() #1 {
+define i32 @foo_off() #1 {
 entry:
   ret i32 43
 }
 
-; CHECK-LABEL: fiz:
+; CHECK-LABEL: foo_off:
+; CHECK-NOT:       pac
 ; CHECK-NOT:       hint
 ; CHECK-NOT:       bti
 ; CHECK:           ret
diff --git a/llvm/test/LTO/AArch64/TestInputs/old.ll b/llvm/test/LTO/AArch64/TestInputs/old.ll
index 119ea6fabbd70a..2b1758b0107a1e 100644
--- a/llvm/test/LTO/AArch64/TestInputs/old.ll
+++ b/llvm/test/LTO/AArch64/TestInputs/old.ll
@@ -1,7 +1,7 @@
-; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
-; Used for test mixing a mixed link case and also verify the import too in llc.
+;; This file contains the previous semantic of the branch-target-enforcement, sign-return-address.
+;; Used for test mixing a mixed link case and also verify the import too in llc.
 
-; RUN: llc %s -o - | FileCheck %s
+; RUN: llc -mattr=+pauth -mattr=+bti %s -o - | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
@@ -12,7 +12,7 @@ entry:
 }
 
 ; CHECK-LABEL: old_bti:
-; CHECK:           hint    #34
+; CHECK:           bti c
 ; CHECK:           mov
 ; CHECK:           ret
 
@@ -22,9 +22,9 @@ entry:
 }
 
 ; CHECK-LABEL: old_pac:
-; CHECK:           hint    #25
-; CHECK:           hint    #29
-; CHECK:           ret
+; CHECK:           paciasp
+; CHECK:           mov
+; CHECK:           retaa
 
 
 define i32 @old_none() #2 {
@@ -38,9 +38,22 @@ entry:
 ; CHECK-NOT:           bti
 ; CHECK:           ret
 
+declare i32 @func(i32)
+
+define i32 @old_none_leaf() #3 {
+entry:
+  %0 = call i32 @func()
+  ret i32 %0
+}
+
+; CHECK-LABEL: old_none_leaf:
+; CHECK:           paciasp
+; CHECK:           bl      func
+; CHECK:           retaa
 
 attributes #0 = { noinline nounwind optnone "branch-target-enforcement"="true" }
-attributes #1 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="all" }
+attributes #1 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="all" "sign-return-address-key"="a_key" }
 attributes #2 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="none" }
+attributes #3 = { noinline nounwind optnone "branch-target-enforcement"="false" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
 
-; Intentionally no module flags
+;; Intentionally no module flags
diff --git a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
index 90b77de70cbf39..aef8907c03411d 100644
--- a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
+++ b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
@@ -1,10 +1,10 @@
-; Testcase to check that module with different branch-target-enforcement can
-; be mixed.
-;
+;; Testcase to check that module with different branch-target-enforcement can
+;; be mixed.
+;;
 ; RUN: llvm-as %s -o %t1.bc
 ; RUN: llvm-as %p/TestInputs/foo.ll -o %t2.bc
 ; RUN: llvm-lto -exported-symbol main \
-; RUN:          -exported-symbol foo \
+; RUN:          -exported-symbol foo_on \
 ; RUN:          -filetype=obj \
 ; RUN:           %t1.bc %t2.bc \
 ; RUN:           -o %t1.exe 2>&1 | FileCheck --allow-empty %s
@@ -14,11 +14,11 @@
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
-declare i32 @foo();
+declare i32 @foo_on();
 
 define i32 @main() "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" {
 entry:
-  %add = call i32 @foo()
+  %add = call i32 @foo_on()
   ret i32 %add
 }
 
@@ -33,9 +33,9 @@ entry:
 ; CHECK-DUMP:      paciasp
 ; CHECK-DUMP:      str
 ; CHECK-DUMP:      bl      0x8 <main+0x8>
-; CHECK-DUMP: <foo>:
+; CHECK-DUMP: <foo_on>:
 ; CHECK-DUMP:     pacibsp
 
-; `main` doesn't support BTI while `foo` does, so in the binary
-; we should see only PAC which is supported by both.
+;; `main` doesn't support BTI while `foo` does, so in the binary
+;; we should see only PAC which is supported by both.
 ; CHECK-PROP:   Properties: aarch64 feature: PAC
\ No newline at end of file
diff --git a/llvm/test/LTO/AArch64/link-sign-return-address.ll b/llvm/test/LTO/AArch64/link-sign-return-address.ll
index 84b4aff10f8c48..df6276f32b6f18 100644
--- a/llvm/test/LTO/AArch64/link-sign-return-address.ll
+++ b/llvm/test/LTO/AArch64/link-sign-return-address.ll
@@ -1,20 +1,23 @@
-; Testcase to check that module with different sign return address can
-; be mixed.
+;; Testcase to check that module with different sign return address can
+;; be mixed.
 ;
 ; RUN: llvm-as %s -o %t1.bc
 ; RUN: llvm-as %p/TestInputs/foo.ll -o %t2.bc
-; RUN: llvm-as %p/TestInputs/bar.ll -o %t3.bc
-; RUN: llvm-as %p/TestInputs/old.ll -o %t4.bc
+; RUN: llvm-as %p/TestInputs/fiz.ll -o %t3.bc
+; RUN: llvm-as %p/TestInputs/bar.ll -o %t4.bc
+; RUN: llvm-as %p/TestInputs/old.ll -o %t5.bc
 ; RUN: llvm-lto -exported-symbol main \
-; RUN:          -exported-symbol foo \
-; RUN:          -exported-symbol fiz \
+; RUN:          -exported-symbol foo_on \
+; RUN:          -exported-symbol foo_off \
+; RUN:          -exported-symbol fiz_on \
+; RUN:          -exported-symbol fiz_off \
 ; RUN:          -exported-symbol bar \
 ; RUN:          -exported-symbol baz \
 ; RUN:          -exported-symbol old_bti \
 ; RUN:          -exported-symbol old_pac \
 ; RUN:          -exported-symbol old_none \
 ; RUN:          -filetype=obj \
-; RUN:          %t4.bc %t3.bc %t2.bc %t1.bc \
+; RUN:          %t5.bc %t4.bc %t3.bc %t2.bc %t1.bc \
 ; RUN:           -o %t1.exe 2>&1
 ; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
 ; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s
@@ -22,8 +25,10 @@
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
-declare i32 @foo();
-declare i32 @fiz();
+declare i32 @foo_on();
+declare i32 @foo_off();
+declare i32 @fiz_on();
+declare i32 @fiz_off();
 declare void @baz();
 declare void @bar();
 declare i32 @old_bti();
@@ -32,8 +37,10 @@ declare i32 @old_none();
 
 define i32 @main() #0 {
 entry:
-  call i32 @foo()
-  call i32 @fiz()
+  call i32 @foo_on()
+  call i32 @foo_off()
+  call i32 @fiz_on()
+  call i32 @fiz_off()
   call void @bar()
   call void @baz()
   call i32 @old_bti()
@@ -70,19 +77,35 @@ attributes #0 = { noinline nounwind optnone }
 ; CHECK-DUMP-NEXT:     ret
 
 ; CHECK-DUMP-LABEL: <baz>:
-; CHECK-DUMP-NEXT:     bti     c
+; CHECK-DUMP-NEXT:     bti c
+; CHECK-DUMP-NEXT:     ret
+
+;; fiz.ll represents a module with the old style of the function attributes.
+;; fiz_on shall have PAC with A-key as it requested at module level.
+; CHECK-DUMP-LABEL: <fiz_on>:
+; CHECK-DUMP-NEXT:     paciasp
+; CHECK-DUMP-NEXT:     str     x30, [sp, #-0x10]!
+; CHECK-DUMP-NEXT:     bl      0x38 <fiz_on+0x8>
+; CHECK-DUMP-NEXT:     mov     w0, #0x2a
+; CHECK-DUMP-NEXT:     ldr     x30, [sp], #0x10
+; CHECK-DUMP-NEXT:     autiasp
 ; CHECK-DUMP-NEXT:     ret
 
-; foo.ll represents a module with the old style of the function attributes.
-; foo shall have PAC with B-key as it requested at module level.
-; CHECK-DUMP-LABEL: <foo>:
+;; fiz_off shall not have BTI or PAC instructions as they are disabled at function scope.
+; CHECK-DUMP-LABEL:  <fiz_off>:
+; CHECK-DUMP-NEXT:       mov     w0, #0x2b
+; CHECK-DUMP-NEXT:       ret
+
+;; foo.ll represents a module with the old style of the function attributes.
+;; foo_on shall have PAC with B-key as it requested at module level.
+; CHECK-DUMP-LABEL: <foo_on>:
 ; CHECK-DUMP-NEXT:     pacibsp
 ; CHECK-DUMP-NEXT:     mov     w0, #0x2a
 ; CHECK-DUMP-NEXT:     autibsp
 ; CHECK-DUMP-NEXT:     ret
 
-; fiz shall not have BTI or PAC instructions as they are disabled at function scope.
-; CHECK-DUMP-LABEL:  <fiz>:
+;; foo_off shall not have BTI or PAC instructions as they are disabled at function scope.
+; CHECK-DUMP-LABEL:  <foo_off>:
 ; CHECK-DUMP-NEXT:       mov     w0, #0x2b
 ; CHECK-DUMP-NEXT:       ret
 
@@ -96,7 +119,9 @@ attributes #0 = { noinline nounwind optnone }
 ; CHECK-DUMP-NEXT:      bl
 ; CHECK-DUMP-NEXT:      bl
 ; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
+; CHECK-DUMP-NEXT:      bl
 
-; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
-; we should not see anything.
+;; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
+;; we should not see anything.
 ; CHECK-PROP-NOT:   Properties: aarch64 feature: PAC
diff --git a/llvm/test/ThinLTO/AArch64/aarch64_inline.ll b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
index 3e286630a52959..a7f6fa920bf226 100644
--- a/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
+++ b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
@@ -30,7 +30,7 @@
 ; CHECK: !3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
 
 
-;--- foo.s
+;--- foo.ll
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
@@ -46,7 +46,7 @@ attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memor
 !2 = !{i32 8, !"sign-return-address-all", i32 1}
 !3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
 
-;--- bar.s
+;--- bar.ll
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
@@ -62,7 +62,7 @@ attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memor
 !2 = !{i32 8, !"sign-return-address-all", i32 2}
 !3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
 
-;--- main.s
+;--- main.ll
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 



More information about the llvm-commits mailing list