[llvm] [PAC][CodeGen][ELF][AArch64] Support signed GOT (PR #113811)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 27 07:32:33 PDT 2024


https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/113811

[PAC][CodeGen][ELF][AArch64] Support signed GOT

This re-applies #96164 after revert in #102434.

Support the following relocations and assembly operators:

- `R_AARCH64_AUTH_ADR_GOT_PAGE` (`:got_auth:` for `adrp`)
- `R_AARCH64_AUTH_LD64_GOT_LO12_NC` (`:got_auth_lo12:` for `ldr`)
- `R_AARCH64_AUTH_GOT_ADD_LO12_NC` (`:got_auth_lo12:` for `add`)

`LOADgotAUTH` pseudo-instruction is introduced which is later expanded to
actual instruction sequence like the following.

```
adrp x16, :got_auth:sym
add x16, x16, :got_auth_lo12:sym
ldr x0, [x16]
autia x0, x16
```

If a resign is requested, like below, `LOADgotPAC` pseudo is used, and GOT
load is lowered similarly to `LOADgotAUTH`.

```
@var = global i32 0
define ptr @resign_globalvar() {
  ret ptr ptrauth (ptr @var, i32 3, i64 43)
}
```

If FPAC bit is not set and auth instruction is emitted, a check+trap sequence
similar to one used for `AUT` pseudo is emitted to ensure auth success.

Both SelectionDAG and GlobalISel are suppported.
For FastISel, we fall back to SelectionDAG.

Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.

See also specification
https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#appendix-signed-got


>From 932e36a43f0f3aa81c55adfc736ce362759f7c28 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 24 Oct 2024 11:16:33 +0300
Subject: [PATCH 1/4] [PAC][CodeGen][ELF][AArch64] Support signed GOT

This re-applies #96164 after revert in #102434.

Support the following relocations and assembly operators:

- `R_AARCH64_AUTH_ADR_GOT_PAGE` (`:got_auth:` for `adrp`)
- `R_AARCH64_AUTH_LD64_GOT_LO12_NC` (`:got_auth_lo12:` for `ldr`)
- `R_AARCH64_AUTH_GOT_ADD_LO12_NC` (`:got_auth_lo12:` for `add`)

`LOADgotAUTH` pseudo-instruction is introduced which is later expanded to
actual instruction sequence like the following.

```
adrp x16, :got_auth:sym
add x16, x16, :got_auth_lo12:sym
ldr x0, [x16]
autia x0, x16
```

If a resign is requested, like below, `LOADgotPAC` pseudo is used, and GOT
load is lowered similarly to `LOADgotAUTH`.

```
@var = global i32 0
define ptr @resign_globalvar() {
  ret ptr ptrauth (ptr @var, i32 3, i64 43)
}
```

If FPAC bit is not set and resign is requested, a check+trap sequence
similar to one used for `AUT` pseudo is emitted.

Both SelectionDAG and GlobalISel are suppported.
For FastISel, we fall back to SelectionDAG.

Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.

See also specification
https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#appendix-signed-got
---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 158 +++++++++++++++++-
 llvm/lib/Target/AArch64/AArch64FastISel.cpp   |   3 +
 .../Target/AArch64/AArch64ISelLowering.cpp    |   5 +
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  11 +-
 .../lib/Target/AArch64/AArch64MCInstLower.cpp |  10 +-
 .../AArch64/AArch64MachineFunctionInfo.cpp    |  13 ++
 .../AArch64/AArch64MachineFunctionInfo.h      |   7 +
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |  32 ++--
 .../GISel/AArch64InstructionSelector.cpp      |   4 +-
 .../MCTargetDesc/AArch64ELFObjectWriter.cpp   |  34 +++-
 .../AArch64/MCTargetDesc/AArch64MCExpr.cpp    |   5 +
 .../AArch64/MCTargetDesc/AArch64MCExpr.h      |   5 +
 .../test/CodeGen/AArch64/ptrauth-basic-pic.ll | 109 ++++++++++++
 .../AArch64/ptrauth-elf-globals-pic.ll        |  29 ++++
 .../ptrauth-elf-got-function-symbols.ll       |  42 +++++
 .../CodeGen/AArch64/ptrauth-extern-weak.ll    |  42 +++++
 .../test/CodeGen/AArch64/ptrauth-got-abuse.ll |  53 ++++++
 .../AArch64/ptrauth-tagged-globals-pic.ll     |  70 ++++++++
 llvm/test/MC/AArch64/adrp-auth-relocation.s   |  12 ++
 llvm/test/MC/AArch64/arm64-elf-relocs.s       |  20 ++-
 llvm/test/MC/AArch64/ilp32-diagnostics.s      |   6 +
 21 files changed, 635 insertions(+), 35 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
 create mode 100644 llvm/test/MC/AArch64/adrp-auth-relocation.s

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 6d2dd0ecbccf31..4f94d12104971f 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -169,6 +169,11 @@ class AArch64AsmPrinter : public AsmPrinter {
   // adrp-add followed by PAC sign)
   void LowerMOVaddrPAC(const MachineInstr &MI);
 
+  // Emit the sequence for LOADgotAUTH (load signed pointer from signed ELF GOT
+  // and authenticate it with, if FPAC bit is not set, check+trap sequence after
+  // authenticating)
+  void LowerLOADgotAUTH(const MachineInstr &MI);
+
   /// tblgen'erated driver function for lowering simple MI->MC
   /// pseudo instructions.
   bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
@@ -873,6 +878,22 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
 
       OutStreamer->addBlankLine();
     }
+
+    // With signed ELF GOT enabled, the linker looks at the symbol type to
+    // choose between keys IA (for STT_FUNC) and DA (for other types). Symbols
+    // for functions not defined in the module have STT_NOTYPE type by default.
+    // This makes linker to emit signing schema with DA key (instead of IA) for
+    // corresponding R_AARCH64_AUTH_GLOB_DAT dynamic reloc. To avoid that, force
+    // all function symbols used in the module to have STT_FUNC type. See
+    // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema
+    const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
+        M.getModuleFlag("ptrauth-elf-got"));
+    if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
+      for (const GlobalValue &GV : M.global_values())
+        if (!GV.use_empty() && isa<Function>(GV) &&
+            !GV.getName().starts_with("llvm."))
+          OutStreamer->emitSymbolAttribute(getSymbol(&GV),
+                                           MCSA_ELF_TypeFunction);
   }
 
   // Emit stack and fault map information.
@@ -2068,6 +2089,10 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) {
 
 void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
   const bool IsGOTLoad = MI.getOpcode() == AArch64::LOADgotPAC;
+  const bool IsELFSignedGOT = MI.getParent()
+                                  ->getParent()
+                                  ->getInfo<AArch64FunctionInfo>()
+                                  ->hasELFSignedGOT();
   MachineOperand GAOp = MI.getOperand(0);
   const uint64_t KeyC = MI.getOperand(1).getImm();
   assert(KeyC <= AArch64PACKey::LAST &&
@@ -2084,9 +2109,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
   // Emit:
   // target materialization:
   // - via GOT:
-  //     adrp x16, :got:target
-  //     ldr x16, [x16, :got_lo12:target]
-  //     add offset to x16 if offset != 0
+  //   - unsigned GOT:
+  //       adrp x16, :got:target
+  //       ldr x16, [x16, :got_lo12:target]
+  //       add offset to x16 if offset != 0
+  //   - ELF signed GOT:
+  //       adrp x17, :got:target
+  //       add x17, x17, :got_auth_lo12:target
+  //       ldr x16, [x17]
+  //       aut{i|d}a x16, x17
+  //       check+trap sequence (if no FPAC)
+  //       add offset to x16 if offset != 0
   //
   // - direct:
   //     adrp x16, target
@@ -2129,13 +2162,79 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
   MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
 
   EmitToStreamer(
-      MCInstBuilder(AArch64::ADRP).addReg(AArch64::X16).addOperand(GAMCHi));
+      MCInstBuilder(AArch64::ADRP)
+          .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
+          .addOperand(GAMCHi));
 
   if (IsGOTLoad) {
-    EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
-                       .addReg(AArch64::X16)
-                       .addReg(AArch64::X16)
-                       .addOperand(GAMCLo));
+    if (IsELFSignedGOT) {
+      EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
+                         .addReg(AArch64::X17)
+                         .addReg(AArch64::X17)
+                         .addOperand(GAMCLo)
+                         .addImm(0));
+
+      EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+                         .addReg(AArch64::X16)
+                         .addReg(AArch64::X17)
+                         .addImm(0));
+
+      assert(GAOp.isGlobal());
+      assert(GAOp.getGlobal()->getValueType() != nullptr);
+      unsigned AuthOpcode = GAOp.getGlobal()->getValueType()->isFunctionTy()
+                                ? AArch64::AUTIA
+                                : AArch64::AUTDA;
+
+      EmitToStreamer(MCInstBuilder(AuthOpcode)
+                         .addReg(AArch64::X16)
+                         .addReg(AArch64::X16)
+                         .addReg(AArch64::X17));
+
+      if (!STI->hasFPAC()) {
+        auto AuthKey = (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA
+                                                     : AArch64PACKey::DA);
+        unsigned XPACOpc = getXPACOpcodeForKey(AuthKey);
+        MCSymbol *SuccessSym = createTempSymbol("auth_success_");
+
+        // XPAC has tied src/dst: use x17 as a temporary copy.
+        //  mov x17, x16
+        EmitToStreamer(MCInstBuilder(AArch64::ORRXrs)
+                           .addReg(AArch64::X17)
+                           .addReg(AArch64::XZR)
+                           .addReg(AArch64::X16)
+                           .addImm(0));
+
+        //  xpaci x17
+        EmitToStreamer(
+            MCInstBuilder(XPACOpc).addReg(AArch64::X17).addReg(AArch64::X17));
+
+        //  cmp x16, x17
+        EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
+                           .addReg(AArch64::XZR)
+                           .addReg(AArch64::X16)
+                           .addReg(AArch64::X17)
+                           .addImm(0));
+
+        //  b.eq Lsuccess
+        EmitToStreamer(
+            MCInstBuilder(AArch64::Bcc)
+                .addImm(AArch64CC::EQ)
+                .addExpr(MCSymbolRefExpr::create(SuccessSym, OutContext)));
+
+        // Trapping sequences do a 'brk'.
+        //  brk #<0xc470 + aut key>
+        EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 | AuthKey));
+
+        // If the auth check succeeds, we can continue.
+        // Lsuccess:
+        OutStreamer->emitLabel(SuccessSym);
+      }
+    } else {
+      EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+                         .addReg(AArch64::X16)
+                         .addReg(AArch64::X16)
+                         .addOperand(GAMCLo));
+    }
   } else {
     EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
                        .addReg(AArch64::X16)
@@ -2203,6 +2302,45 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
   EmitToStreamer(MIB);
 }
 
+void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
+  Register DstReg = MI.getOperand(0).getReg();
+  const MachineOperand &GAMO = MI.getOperand(1);
+  assert(GAMO.getOffset() == 0);
+
+  MachineOperand GAHiOp(GAMO);
+  MachineOperand GALoOp(GAMO);
+  GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
+  GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+
+  MCOperand GAMCHi, GAMCLo;
+  MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
+  MCInstLowering.lowerOperand(GALoOp, GAMCLo);
+
+  EmitToStreamer(
+      MCInstBuilder(AArch64::ADRP).addReg(AArch64::X16).addOperand(GAMCHi));
+
+  EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
+                     .addReg(AArch64::X16)
+                     .addReg(AArch64::X16)
+                     .addOperand(GAMCLo)
+                     .addImm(0));
+
+  EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+                     .addReg(DstReg)
+                     .addReg(AArch64::X16)
+                     .addImm(0));
+
+  assert(GAMO.isGlobal());
+  assert(GAMO.getGlobal()->getValueType() != nullptr);
+  unsigned AuthOpcode = GAMO.getGlobal()->getValueType()->isFunctionTy()
+                            ? AArch64::AUTIA
+                            : AArch64::AUTDA;
+  EmitToStreamer(MCInstBuilder(AuthOpcode)
+                     .addReg(DstReg)
+                     .addReg(DstReg)
+                     .addReg(AArch64::X16));
+}
+
 const MCExpr *
 AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
   const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant(BA);
@@ -2381,6 +2519,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
     LowerMOVaddrPAC(*MI);
     return;
 
+  case AArch64::LOADgotAUTH:
+    LowerLOADgotAUTH(*MI);
+    return;
+
   case AArch64::BRA:
   case AArch64::BLRA:
     emitPtrauthBranch(MI);
diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
index cbf38f2c57a35e..4487d34a936c4d 100644
--- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
@@ -453,6 +453,9 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
   if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())
     return 0;
 
+  if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
+    return 0;
+
   unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);
 
   EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 4c0cd1ac3d4512..884e5fe9f60040 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9598,6 +9598,11 @@ SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG,
   SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags);
   // FIXME: Once remat is capable of dealing with instructions with register
   // operands, expand this into two nodes instead of using a wrapper node.
+  if (DAG.getMachineFunction()
+          .getInfo<AArch64FunctionInfo>()
+          ->hasELFSignedGOT())
+    return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr),
+                   0);
   return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr);
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index fe3c8578b52aa4..a1fbe557bf2338 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1937,8 +1937,15 @@ let Predicates = [HasPAuth] in {
                Sched<[WriteI, ReadI]> {
     let isReMaterializable = 1;
     let isCodeGenOnly = 1;
-    let Size = 40; // 12 fixed + 28 variable, for pointer offset, and discriminator
-    let Defs = [X16,X17];
+    let Size = 68; // 12 fixed + 56 variable, for pointer offset, discriminator and
+                   // ELF signed GOT signed pointer authentication (if no FPAC)
+    let Defs = [X16,X17,NZCV];
+  }
+
+  def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>,
+               Sched<[WriteI, ReadI]> {
+    let Defs = [X16];
+    let Size = 16;
   }
 
   // Load a signed global address from a special $auth_ptr$ stub slot.
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index 48672241f905d5..9f234b0f917058 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AArch64MCInstLower.h"
+#include "AArch64MachineFunctionInfo.h"
 #include "MCTargetDesc/AArch64MCExpr.h"
 #include "Utils/AArch64BaseInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -185,9 +186,12 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
                                                     MCSymbol *Sym) const {
   uint32_t RefFlags = 0;
 
-  if (MO.getTargetFlags() & AArch64II::MO_GOT)
-    RefFlags |= AArch64MCExpr::VK_GOT;
-  else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
+  if (MO.getTargetFlags() & AArch64II::MO_GOT) {
+    const MachineFunction *MF = MO.getParent()->getParent()->getParent();
+    RefFlags |= (MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
+                     ? AArch64MCExpr::VK_GOT_AUTH
+                     : AArch64MCExpr::VK_GOT);
+  } else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
     TLSModel::Model Model;
     if (MO.isGlobal()) {
       const GlobalValue *GV = MO.getGlobal();
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
index e96c5a953ff2bb..56a38bc6d4023a 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
@@ -72,6 +72,18 @@ static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
   return Key == "b_key";
 }
 
+static bool HasELFSignedGOTHelper(const Function &F,
+                                  const AArch64Subtarget *STI) {
+  if (!Triple(STI->getTargetTriple()).isOSBinFormatELF())
+    return false;
+  const Module *M = F.getParent();
+  const auto *Flag = mdconst::extract_or_null<ConstantInt>(
+      M->getModuleFlag("ptrauth-elf-got"));
+  if (Flag && Flag->getZExtValue() == 1)
+    return true;
+  return false;
+}
+
 AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
                                          const AArch64Subtarget *STI) {
   // If we already know that the function doesn't have a redzone, set
@@ -80,6 +92,7 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
     HasRedZone = false;
   std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
   SignWithBKey = ShouldSignWithBKey(F, *STI);
+  HasELFSignedGOT = HasELFSignedGOTHelper(F, STI);
   // TODO: skip functions that have no instrumented allocas for optimization
   IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);
 
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 85b9733e95c529..a77fdaf19bcf5f 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -177,6 +177,11 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
   /// SignWithBKey modifies the default PAC-RET mode to signing with the B key.
   bool SignWithBKey = false;
 
+  /// HasELFSignedGOT is true if the target binary format is ELF and the IR
+  /// module containing the corresponding function has "ptrauth-elf-got" flag
+  /// set to 1.
+  bool HasELFSignedGOT = false;
+
   /// SigningInstrOffset captures the offset of the PAC-RET signing instruction
   /// within the prologue, so it can be re-used for authentication in the
   /// epilogue when using PC as a second salt (FEAT_PAuth_LR)
@@ -509,6 +514,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
 
   bool shouldSignWithBKey() const { return SignWithBKey; }
 
+  bool hasELFSignedGOT() const { return HasELFSignedGOT; }
+
   MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; }
   void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; }
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index dfc5e04110cf57..b83ca3f7e52db4 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -896,6 +896,7 @@ class AArch64Operand : public MCParsedAsmOperand {
     if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
         ELFRefKind == AArch64MCExpr::VK_LO12 ||
         ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
+        ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
         ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
         ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
         ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
@@ -1007,19 +1008,20 @@ class AArch64Operand : public MCParsedAsmOperand {
     int64_t Addend;
     if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
                                           DarwinRefKind, Addend)) {
-      return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
-          || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
-          || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
-          || ELFRefKind == AArch64MCExpr::VK_LO12
-          || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
-          || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
-          || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
-          || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
-          || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
-          || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
-          || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
-          || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
-          || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
+      return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
+             DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF ||
+             (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) ||
+             ELFRefKind == AArch64MCExpr::VK_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
+             ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
+             ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
+             ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
+             ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 ||
+             ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
     }
 
     // If it's a constant, it should be a real immediate in range.
@@ -3308,6 +3310,7 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
                DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
                ELFRefKind != AArch64MCExpr::VK_ABS_PAGE_NC &&
                ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
+               ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
                ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 &&
                ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
                ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
@@ -4427,6 +4430,8 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
                   .Case("got", AArch64MCExpr::VK_GOT_PAGE)
                   .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15)
                   .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
+                  .Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE)
+                  .Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12)
                   .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
                   .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
                   .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
@@ -5800,6 +5805,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
 
         // Only allow these with ADDXri/ADDWri
         if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
+             ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
              ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
              ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
              ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index df0c09d32c074a..1c75868645a947 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2959,7 +2959,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
     }
 
     if (OpFlags & AArch64II::MO_GOT) {
-      I.setDesc(TII.get(AArch64::LOADgot));
+      I.setDesc(TII.get(MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
+                            ? AArch64::LOADgotAUTH
+                            : AArch64::LOADgot));
       I.getOperand(1).setTargetFlags(OpFlags);
     } else if (TM.getCodeModel() == CodeModel::Large &&
                !TM.isPositionIndependent()) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index 83aac6fdae7290..b5f5a58d96288e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -165,6 +165,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
       }
       if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
         return R_CLS(ADR_GOT_PAGE);
+      if (SymLoc == AArch64MCExpr::VK_GOT_AUTH && !IsNC) {
+        if (IsILP32) {
+          Ctx.reportError(Fixup.getLoc(),
+                          "ILP32 ADRP AUTH relocation not supported "
+                          "(LP64 eqv: AUTH_ADR_GOT_PAGE)");
+          return ELF::R_AARCH64_NONE;
+        }
+        return ELF::R_AARCH64_AUTH_ADR_GOT_PAGE;
+      }
       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
         return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
       if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
@@ -240,6 +249,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
         return R_CLS(TLSLE_ADD_TPREL_LO12);
       if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
         return R_CLS(TLSDESC_ADD_LO12);
+      if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) {
+        if (IsILP32) {
+          Ctx.reportError(Fixup.getLoc(),
+                          "ILP32 ADD AUTH relocation not supported "
+                          "(LP64 eqv: AUTH_GOT_ADD_LO12_NC)");
+          return ELF::R_AARCH64_NONE;
+        }
+        return ELF::R_AARCH64_AUTH_GOT_ADD_LO12_NC;
+      }
       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
         return R_CLS(ADD_ABS_LO12_NC);
 
@@ -332,17 +350,23 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
     case AArch64::fixup_aarch64_ldst_imm12_scale8:
       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
         return R_CLS(LDST64_ABS_LO12_NC);
-      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
+      if ((SymLoc == AArch64MCExpr::VK_GOT ||
+           SymLoc == AArch64MCExpr::VK_GOT_AUTH) &&
+          IsNC) {
         AArch64MCExpr::VariantKind AddressLoc =
             AArch64MCExpr::getAddressFrag(RefKind);
+        bool IsAuth = (SymLoc == AArch64MCExpr::VK_GOT_AUTH);
         if (!IsILP32) {
           if (AddressLoc == AArch64MCExpr::VK_LO15)
             return ELF::R_AARCH64_LD64_GOTPAGE_LO15;
-          return ELF::R_AARCH64_LD64_GOT_LO12_NC;
+          return (IsAuth ? ELF::R_AARCH64_AUTH_LD64_GOT_LO12_NC
+                         : ELF::R_AARCH64_LD64_GOT_LO12_NC);
         }
-        Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
-                                        "relocation not supported (LP64 eqv: "
-                                        "LD64_GOT_LO12_NC)");
+        Ctx.reportError(Fixup.getLoc(),
+                        Twine("ILP32 64-bit load/store "
+                              "relocation not supported (LP64 eqv: ") +
+                            (IsAuth ? "AUTH_GOT_LO12_NC" : "LD64_GOT_LO12_NC") +
+                            Twine(')'));
         return ELF::R_AARCH64_NONE;
       }
       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
index fb8eb9f47da179..3430b9002894f0 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
@@ -30,6 +30,7 @@ const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind,
 }
 
 StringRef AArch64MCExpr::getVariantKindName() const {
+  // clang-format off
   switch (static_cast<uint32_t>(getKind())) {
   case VK_CALL:                return "";
   case VK_LO12:                return ":lo12:";
@@ -82,9 +83,13 @@ StringRef AArch64MCExpr::getVariantKindName() const {
   case VK_TLSDESC_PAGE:        return ":tlsdesc:";
   case VK_SECREL_LO12:         return ":secrel_lo12:";
   case VK_SECREL_HI12:         return ":secrel_hi12:";
+  case VK_GOT_AUTH:            return ":got_auth:";
+  case VK_GOT_AUTH_PAGE:       return ":got_auth:";
+  case VK_GOT_AUTH_LO12:       return ":got_auth_lo12:";
   default:
     llvm_unreachable("Invalid ELF symbol kind");
   }
+  // clang-format on
 }
 
 void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
index cf3a90f95a2c16..699992782f67b8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
@@ -24,6 +24,7 @@ namespace llvm {
 class AArch64MCExpr : public MCTargetExpr {
 public:
   enum VariantKind {
+    // clang-format off
     // Symbol locations specifying (roughly speaking) what calculation should be
     // performed to construct the final address for the relocated
     // symbol. E.g. direct, via the GOT, ...
@@ -38,6 +39,7 @@ class AArch64MCExpr : public MCTargetExpr {
     VK_SECREL   = 0x009,
     VK_AUTH     = 0x00a,
     VK_AUTHADDR = 0x00b,
+    VK_GOT_AUTH = 0x00c,
     VK_SymLocBits = 0x00f,
 
     // Variants specifying which part of the final address calculation is
@@ -88,6 +90,8 @@ class AArch64MCExpr : public MCTargetExpr {
     VK_GOT_LO12          = VK_GOT      | VK_PAGEOFF | VK_NC,
     VK_GOT_PAGE          = VK_GOT      | VK_PAGE,
     VK_GOT_PAGE_LO15     = VK_GOT      | VK_LO15    | VK_NC,
+    VK_GOT_AUTH_LO12     = VK_GOT_AUTH | VK_PAGEOFF | VK_NC,
+    VK_GOT_AUTH_PAGE     = VK_GOT_AUTH | VK_PAGE,
     VK_DTPREL_G2         = VK_DTPREL   | VK_G2,
     VK_DTPREL_G1         = VK_DTPREL   | VK_G1,
     VK_DTPREL_G1_NC      = VK_DTPREL   | VK_G1      | VK_NC,
@@ -114,6 +118,7 @@ class AArch64MCExpr : public MCTargetExpr {
     VK_SECREL_HI12       = VK_SECREL   | VK_HI12,
 
     VK_INVALID  = 0xfff
+    // clang-format on
   };
 
 private:
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
new file mode 100644
index 00000000000000..88cf356214feba
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
@@ -0,0 +1,109 @@
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0         -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0         -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
+
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1         -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1         -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
+
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \
+; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
+
+;; Note: for FastISel, we fall back to SelectionDAG
+
+ at var = global i32 0
+
+define i32 @get_globalvar() {
+; CHECK-LABEL: get_globalvar:
+; CHECK:         adrp  x16, :got_auth:var
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
+; CHECK-NEXT:    ldr   x8,  [x16]
+; CHECK-NEXT:    autda x8,  x16
+; CHECK-NEXT:    ldr   w0,  [x8]
+; CHECK-NEXT:    ret
+
+  %val = load i32, ptr @var
+  ret i32 %val
+}
+
+define ptr @get_globalvaraddr() {
+; CHECK-LABEL: get_globalvaraddr:
+; CHECK:         adrp  x16, :got_auth:var
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
+; CHECK-NEXT:    ldr   x0,  [x16]
+; CHECK-NEXT:    autda x0,  x16
+; CHECK-NEXT:    ret
+
+  %val = load i32, ptr @var
+  ret ptr @var
+}
+
+declare i32 @foo()
+
+define ptr @resign_globalfunc() {
+; CHECK-LABEL: resign_globalfunc:
+; CHECK:         adrp  x17, :got_auth:foo
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:foo
+; CHECK-NEXT:    ldr   x16, [x17]
+; CHECK-NEXT:    autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_0:
+; CHECK-NEXT:    mov   x17, #42
+; CHECK-NEXT:    pacia x16, x17
+; CHECK-NEXT:    mov   x0,  x16
+; CHECK-NEXT:    ret
+
+  ret ptr ptrauth (ptr @foo, i32 0, i64 42)
+}
+
+define ptr @resign_globalvar() {
+; CHECK-LABEL: resign_globalvar:
+; CHECK:         adrp  x17, :got_auth:var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var
+; CHECK-NEXT:    ldr   x16, [x17]
+; CHECK-NEXT:    autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_1:
+; CHECK-NEXT:    mov   x17, #43
+; CHECK-NEXT:    pacdb x16, x17
+; CHECK-NEXT:    mov   x0,  x16
+; CHECK-NEXT:    ret
+
+  ret ptr ptrauth (ptr @var, i32 3, i64 43)
+}
+
+define ptr @resign_globalvar_offset() {
+; CHECK-LABEL: resign_globalvar_offset:
+; CHECK:         adrp  x17, :got_auth:var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var
+; CHECK-NEXT:    ldr   x16, [x17]
+; CHECK-NEXT:    autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_2
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_2:
+; CHECK-NEXT:    add   x16, x16, #16
+; CHECK-NEXT:    mov   x17, #44
+; CHECK-NEXT:    pacda x16, x17
+; CHECK-NEXT:    mov   x0,  x16
+; CHECK-NEXT:    ret
+
+  ret ptr ptrauth (ptr getelementptr (i8, ptr @var, i64 16), i32 2, i64 44)
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
new file mode 100644
index 00000000000000..7531df06b99d08
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
@@ -0,0 +1,29 @@
+; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0         -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1         -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+; RUN: llc -mtriple=arm64 -global-isel=1 -global-isel-abort=1 -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+
+;; Note: for FastISel, we fall back to SelectionDAG
+
+ at var8 = external global i8, align 1
+
+define i8 @test_i8(i8 %new) {
+  %val = load i8, ptr @var8, align 1
+  store i8 %new, ptr @var8
+  ret i8 %val
+
+; CHECK-LABEL: test_i8:
+; CHECK:         adrp  x16, :got_auth:var8
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var8
+; CHECK-NEXT:    ldr   x9,  [x16]
+; CHECK-NEXT:    autda x9,  x16
+; CHECK-NEXT:    ldrb  w8,  [x9]
+; CHECK-NEXT:    strb  w0,  [x9]
+; CHECK-NEXT:    mov   x0,  x8
+; CHECK-NEXT:    ret
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll
new file mode 100644
index 00000000000000..e75acceaa0d121
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll
@@ -0,0 +1,42 @@
+; RUN: llc -mtriple aarch64-linux-pauthtest -mattr +pauth -filetype=asm %s -o - | \
+; RUN:   FileCheck %s --check-prefix=ASM
+; RUN: llc -mtriple aarch64-linux-pauthtest -mattr +pauth -filetype=obj %s -o - | \
+; RUN:   llvm-readelf -s - | FileCheck %s --check-prefix=OBJ
+
+; ASM:               .type   foo, at function
+; ASM-LABEL: foo:
+; ASM:               adrp    x17, :got_auth:bar
+; ASM-NEXT:          add     x17, x17, :got_auth_lo12:bar
+; ASM-NEXT:          ldr     x16, [x17]
+; ASM-NEXT:          autia   x16, x17
+; ASM-NEXT:          mov     x17, x16
+; ASM-NEXT:          xpaci   x17
+; ASM-NEXT:          cmp     x16, x17
+; ASM-NEXT:          b.eq    .Lauth_success_0
+; ASM-NEXT:          brk     #0xc470
+; ASM-NEXT:  .Lauth_success_0:
+; ASM-NEXT:          paciza  x16
+; ASM-NEXT:          adrp    x8, .Lfptr
+; ASM-NEXT:          str     x16, [x8, :lo12:.Lfptr]
+; ASM-NEXT:          ret
+; ASM:               .type   .Lfptr, at object
+; ASM-NEXT:          .local  .Lfptr
+; ASM-NEXT:          .comm   .Lfptr,8,8
+; ASM:               .type   bar, at function
+
+; OBJ:      Symbol table '.symtab' contains [[#]] entries:
+; OBJ-NEXT:    Num:    Value          Size Type    Bind   Vis       Ndx Name
+; OBJ:              0000000000000000     0 FUNC    GLOBAL DEFAULT   UND bar
+
+ at fptr = private global ptr null
+
+define void @foo() {
+  store ptr ptrauth (ptr @bar, i32 0), ptr @fptr
+  ret void
+}
+
+declare i32 @bar()
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
new file mode 100644
index 00000000000000..01d1ac564f5f11
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
@@ -0,0 +1,42 @@
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0         -relocation-model=pic \
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1         -relocation-model=pic \
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+
+;; Note: for FastISel, we fall back to SelectionDAG
+
+declare extern_weak dso_local i32 @var()
+
+define ptr @foo() {
+; The usual ADRP/ADD pair can't be used for a weak reference because it must
+; evaluate to 0 if the symbol is undefined. We use a GOT entry for PIC
+; otherwise a litpool entry.
+  ret ptr @var
+
+; CHECK-LABEL: foo:
+; CHECK:         adrp  x16, :got_auth:var
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
+; CHECK-NEXT:    ldr   x0,  [x16]
+; CHECK-NEXT:    autia x0,  x16
+; CHECK-NEXT:    ret
+}
+
+ at arr_var = extern_weak global [10 x i32]
+
+define ptr @bar() {
+  %addr = getelementptr [10 x i32], ptr @arr_var, i32 0, i32 5
+  ret ptr %addr
+
+; CHECK-LABEL: bar:
+; CHECK:         adrp  x16, :got_auth:arr_var
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:arr_var
+; CHECK-NEXT:    ldr   x8,  [x16]
+; CHECK-NEXT:    autda x8,  x16
+; CHECK-NEXT:    add   x0,  x8, #20
+; CHECK-NEXT:    ret
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
new file mode 100644
index 00000000000000..8a7a48716be2c0
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
@@ -0,0 +1,53 @@
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0         \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1         \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0         \
+; RUN:   -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1         \
+; RUN:   -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \
+; RUN:   -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s
+
+;; Note: for FastISel, we fall back to SelectionDAG
+
+declare void @consume(i32)
+declare void @func()
+
+define void @aliasee_func() {
+  ret void
+}
+ at alias_func = alias void (), ptr @aliasee_func
+
+ at aliasee_global = global i32 42
+ at alias_global = alias i32, ptr @aliasee_global
+
+define void @foo() nounwind {
+; CHECK-LABEL: foo:
+entry:
+  call void @consume(i32 ptrtoint (ptr @func to i32))
+; CHECK:         adrp  x16, :got_auth:func
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:func
+; CHECK-NEXT:    ldr   x[[TMP0:[0-9]+]], [x16]
+; CHECK-NEXT:    autia x[[TMP0]], x16
+
+  call void @consume(i32 ptrtoint (ptr @alias_func to i32))
+; CHECK:         adrp  x16, :got_auth:alias_func
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:alias_func
+; CHECK-NEXT:    ldr   x[[TMP1:[0-9]+]], [x16]
+; CHECK-NEXT:    autia x[[TMP1]], x16
+
+  call void @consume(i32 ptrtoint (ptr @alias_global to i32))
+; CHECK:         adrp  x16, :got_auth:alias_global
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:alias_global
+; CHECK-NEXT:    ldr   x[[TMP2:[0-9]+]], [x16]
+; CHECK-NEXT:    autda x[[TMP2]], x16
+
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
new file mode 100644
index 00000000000000..9da7044761d648
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
@@ -0,0 +1,70 @@
+; RUN: llc -global-isel=0 -fast-isel=0 -O0         --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL
+; RUN: llc -global-isel=0 -fast-isel=1 -O0         --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL
+; RUN: llc -global-isel=1 -global-isel-abort=1 -O0 --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,GISEL
+
+;; Note: for FastISel, we fall back to SelectionDAG
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-android"
+
+ at global = external global i32
+declare void @func()
+
+define ptr @global_addr() #0 {
+; CHECK-LABEL: global_addr:
+; CHECK:         adrp  x16, :got_auth:global
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:global
+; CHECK-NEXT:    ldr   x0,  [x16]
+; CHECK-NEXT:    autda x0,  x16
+; CHECK-NEXT:    ret
+
+  ret ptr @global
+}
+
+define i32 @global_load() #0 {
+; CHECK-LABEL: global_load:
+; CHECK:         adrp  x16, :got_auth:global
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:global
+; CHECK-NEXT:    ldr   x8,  [x16]
+; CHECK-NEXT:    autda x8,  x16
+; CHECK-NEXT:    ldr   w0,  [x8]
+; CHECK-NEXT:    ret
+
+  %load = load i32, ptr @global
+  ret i32 %load
+}
+
+define void @global_store() #0 {
+; CHECK-LABEL:   global_store:
+; CHECK:           adrp  x16, :got_auth:global
+; CHECK-NEXT:      add   x16, x16, :got_auth_lo12:global
+; GISEL-NEXT:      ldr   x8,  [x16]
+; GISEL-NEXT:      autda x8,  x16
+; GISEL-NEXT:      str   wzr, [x8]
+; DAGISEL-NEXT:    ldr   x9,  [x16]
+; DAGISEL-NEXT:    autda x9,  x16
+; DAGISEL-NEXT:    mov   w8,  wzr
+; DAGISEL-NEXT:    str   w8,  [x9]
+; CHECK-NEXT:      ret
+  store i32 0, ptr @global
+  ret void
+}
+
+define ptr @func_addr() #0 {
+; CHECK-LABEL: func_addr:
+; CHECK:         adrp  x16, :got_auth:func
+; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:func
+; CHECK-NEXT:    ldr   x0,  [x16]
+; CHECK-NEXT:    autia x0,  x16
+; CHECK-NEXT:    ret
+
+  ret ptr @func
+}
+
+attributes #0 = { "target-features"="+tagged-globals" }
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/MC/AArch64/adrp-auth-relocation.s b/llvm/test/MC/AArch64/adrp-auth-relocation.s
new file mode 100644
index 00000000000000..57021c71632ff3
--- /dev/null
+++ b/llvm/test/MC/AArch64/adrp-auth-relocation.s
@@ -0,0 +1,12 @@
+// RUN: llvm-mc -triple=aarch64-linux-gnu -filetype=obj -o - %s | llvm-readobj -r - | FileCheck %s
+// RUN: not llvm-mc -triple=aarch64-linux-gnu_ilp32 -filetype=obj \
+// RUN:   -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-ILP32 %s
+
+.text
+adrp x0, :got_auth:sym
+
+.global sym
+sym:
+
+// CHECK: R_AARCH64_AUTH_ADR_GOT_PAGE sym
+// CHECK-ILP32: error: ILP32 ADRP AUTH relocation not supported (LP64 eqv: AUTH_ADR_GOT_PAGE)
diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s
index 8813c4bd7d1aa1..f679bb4c82827b 100644
--- a/llvm/test/MC/AArch64/arm64-elf-relocs.s
+++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s
@@ -81,13 +81,17 @@
 // CHECK: adrp x15, :got:sym
 // CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym
 
+   adrp x15, :got_auth:sym
+// CHECK: adrp x15, :got_auth:sym
+// CHECK-OBJ-LP64: 5c R_AARCH64_AUTH_ADR_GOT_PAGE sym
+
    adrp x29, :gottprel:sym
 // CHECK: adrp x29, :gottprel:sym
-// CHECK-OBJ-LP64: 5c R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym
+// CHECK-OBJ-LP64: 60 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym
 
    adrp x2, :tlsdesc:sym
 // CHECK: adrp x2, :tlsdesc:sym
-// CHECK-OBJ-LP64: 60 R_AARCH64_TLSDESC_ADR_PAGE21 sym
+// CHECK-OBJ-LP64: 64 R_AARCH64_TLSDESC_ADR_PAGE21 sym
 
    // LLVM is not competent enough to do this relocation because the
    // page boundary could occur anywhere after linking. A relocation
@@ -96,7 +100,7 @@
    .global trickQuestion
 trickQuestion:
 // CHECK: adrp x3, trickQuestion
-// CHECK-OBJ-LP64: 64 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion
+// CHECK-OBJ-LP64: 68 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion
 
    ldrb w2, [x3, :lo12:sym]
    ldrsb w5, [x7, #:lo12:sym]
@@ -245,6 +249,16 @@ trickQuestion:
 // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym
 // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym+0x7
 
+   ldr x24, [x23, #:got_auth_lo12:sym]
+   ldr d22, [x21, :got_auth_lo12:sym]
+   ldr x24, [x23, :got_auth_lo12:sym+7]
+// CHECK: ldr x24, [x23, :got_auth_lo12:sym]
+// CHECK: ldr d22, [x21, :got_auth_lo12:sym]
+// CHECK: ldr x24, [x23, :got_auth_lo12:sym+7]
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym+0x7
+
   ldr x24, [x23, #:gotpage_lo15:sym]
   ldr d22, [x21, :gotpage_lo15:sym]
   ldr d22, [x23, :gotpage_lo15:sym+7]
diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s
index 8a3bc1398e0429..5d9c6e5626b2b3 100644
--- a/llvm/test/MC/AArch64/ilp32-diagnostics.s
+++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s
@@ -69,6 +69,12 @@ ldr x10, [x0, #:gottprel_lo12:var]
 ldr x24, [x23, #:got_lo12:sym]
 // ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: LD64_GOT_LO12_NC)
 
+ldr x24, [x23, #:got_auth_lo12:sym]
+// ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: AUTH_GOT_LO12_NC)
+
+add x24, x23, #:got_auth_lo12:sym
+// ERROR: [[#@LINE-1]]:1: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADD_LO12_NC)
+
 ldr x24, [x23, :gottprel_lo12:sym]
 // ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: TLSIE_LD64_GOTTPREL_LO12_NC)
 

>From f0044c35b05295bb49848454136925f61d2c2d02 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 24 Oct 2024 18:11:36 +0300
Subject: [PATCH 2/4] [PAC][CodeGen] Use `emitPtrauthCheckAuthenticatedValue`
 in `LowerMOVaddrPAC`

---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 37 ++-----------------
 1 file changed, 3 insertions(+), 34 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4f94d12104971f..ecc94a47071a4c 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2193,41 +2193,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
       if (!STI->hasFPAC()) {
         auto AuthKey = (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA
                                                      : AArch64PACKey::DA);
-        unsigned XPACOpc = getXPACOpcodeForKey(AuthKey);
-        MCSymbol *SuccessSym = createTempSymbol("auth_success_");
 
-        // XPAC has tied src/dst: use x17 as a temporary copy.
-        //  mov x17, x16
-        EmitToStreamer(MCInstBuilder(AArch64::ORRXrs)
-                           .addReg(AArch64::X17)
-                           .addReg(AArch64::XZR)
-                           .addReg(AArch64::X16)
-                           .addImm(0));
-
-        //  xpaci x17
-        EmitToStreamer(
-            MCInstBuilder(XPACOpc).addReg(AArch64::X17).addReg(AArch64::X17));
-
-        //  cmp x16, x17
-        EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
-                           .addReg(AArch64::XZR)
-                           .addReg(AArch64::X16)
-                           .addReg(AArch64::X17)
-                           .addImm(0));
-
-        //  b.eq Lsuccess
-        EmitToStreamer(
-            MCInstBuilder(AArch64::Bcc)
-                .addImm(AArch64CC::EQ)
-                .addExpr(MCSymbolRefExpr::create(SuccessSym, OutContext)));
-
-        // Trapping sequences do a 'brk'.
-        //  brk #<0xc470 + aut key>
-        EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 | AuthKey));
-
-        // If the auth check succeeds, we can continue.
-        // Lsuccess:
-        OutStreamer->emitLabel(SuccessSym);
+        emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
+                                           /*ShouldTrap=*/true,
+                                           /*OnFailure=*/nullptr);
       }
     } else {
       EmitToStreamer(MCInstBuilder(AArch64::LDRXui)

>From c1dd585f547abcfad542c1e61a2417344e7d2d7a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 25 Oct 2024 11:25:14 +0300
Subject: [PATCH 3/4] [PAC][CodeGen] Fix handling of extern_weak symbols with
 signed GOT

Before executing auth instruction on a signed address from a GOT slot,
we must ensure that the address is not zero since zero addresses are not
signed to preserve zero-checks working as expected. A GOT slot might be
filled with zero when we have an undefined weak symbol.
---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp    | 12 ++++++++++++
 llvm/lib/Target/AArch64/AArch64InstrInfo.td      |  2 +-
 llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll |  4 ++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index ecc94a47071a4c..6438322974897a 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2300,6 +2300,15 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
                      .addImm(0));
 
   assert(GAMO.isGlobal());
+  MCSymbol *UndefWeakSym;
+  if (GAMO.getGlobal()->hasExternalWeakLinkage()) {
+    UndefWeakSym = createTempSymbol("undef_weak");
+    EmitToStreamer(
+        MCInstBuilder(AArch64::CBZX)
+            .addReg(DstReg)
+            .addExpr(MCSymbolRefExpr::create(UndefWeakSym, OutContext)));
+  }
+
   assert(GAMO.getGlobal()->getValueType() != nullptr);
   unsigned AuthOpcode = GAMO.getGlobal()->getValueType()->isFunctionTy()
                             ? AArch64::AUTIA
@@ -2308,6 +2317,9 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
                      .addReg(DstReg)
                      .addReg(DstReg)
                      .addReg(AArch64::X16));
+
+  if (GAMO.getGlobal()->hasExternalWeakLinkage())
+    OutStreamer->emitLabel(UndefWeakSym);
 }
 
 const MCExpr *
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a1fbe557bf2338..59ba461d4eb071 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1945,7 +1945,7 @@ let Predicates = [HasPAuth] in {
   def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>,
                Sched<[WriteI, ReadI]> {
     let Defs = [X16];
-    let Size = 16;
+    let Size = 20;
   }
 
   // Load a signed global address from a special $auth_ptr$ stub slot.
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
index 01d1ac564f5f11..bd72b81eeea48e 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
@@ -19,7 +19,9 @@ define ptr @foo() {
 ; CHECK:         adrp  x16, :got_auth:var
 ; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
 ; CHECK-NEXT:    ldr   x0,  [x16]
+; CHECK-NEXT:    cbz   x0, .Lundef_weak0
 ; CHECK-NEXT:    autia x0,  x16
+; CHECK-NEXT:  .Lundef_weak0:
 ; CHECK-NEXT:    ret
 }
 
@@ -33,7 +35,9 @@ define ptr @bar() {
 ; CHECK:         adrp  x16, :got_auth:arr_var
 ; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:arr_var
 ; CHECK-NEXT:    ldr   x8,  [x16]
+; CHECK-NEXT:    cbz   x8, .Lundef_weak1
 ; CHECK-NEXT:    autda x8,  x16
+; CHECK-NEXT:  .Lundef_weak1:
 ; CHECK-NEXT:    add   x0,  x8, #20
 ; CHECK-NEXT:    ret
 }

>From a5688e5550e5b7263e0980509037d3ce6e536eec Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 25 Oct 2024 11:28:34 +0300
Subject: [PATCH 4/4] [PAC][CodeGen] Emit trap sequence w/o FPAC on LOADgotAUTH
 expansion

---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 30 ++++--
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  4 +-
 .../test/CodeGen/AArch64/ptrauth-basic-pic.ll | 52 ++++++----
 .../AArch64/ptrauth-elf-globals-pic.ll        | 31 ++++--
 .../CodeGen/AArch64/ptrauth-extern-weak.ll    | 54 +++++++---
 .../test/CodeGen/AArch64/ptrauth-got-abuse.ll | 65 +++++++++---
 .../AArch64/ptrauth-tagged-globals-pic.ll     | 99 ++++++++++++++-----
 7 files changed, 246 insertions(+), 89 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 6438322974897a..e79457f925db66 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2273,6 +2273,7 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
 
 void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
   Register DstReg = MI.getOperand(0).getReg();
+  Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
   const MachineOperand &GAMO = MI.getOperand(1);
   assert(GAMO.getOffset() == 0);
 
@@ -2286,17 +2287,17 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
   MCInstLowering.lowerOperand(GALoOp, GAMCLo);
 
   EmitToStreamer(
-      MCInstBuilder(AArch64::ADRP).addReg(AArch64::X16).addOperand(GAMCHi));
+      MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
 
   EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
-                     .addReg(AArch64::X16)
-                     .addReg(AArch64::X16)
+                     .addReg(AArch64::X17)
+                     .addReg(AArch64::X17)
                      .addOperand(GAMCLo)
                      .addImm(0));
 
   EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
-                     .addReg(DstReg)
-                     .addReg(AArch64::X16)
+                     .addReg(AuthResultReg)
+                     .addReg(AArch64::X17)
                      .addImm(0));
 
   assert(GAMO.isGlobal());
@@ -2305,7 +2306,7 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
     UndefWeakSym = createTempSymbol("undef_weak");
     EmitToStreamer(
         MCInstBuilder(AArch64::CBZX)
-            .addReg(DstReg)
+            .addReg(AuthResultReg)
             .addExpr(MCSymbolRefExpr::create(UndefWeakSym, OutContext)));
   }
 
@@ -2314,12 +2315,23 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
                             ? AArch64::AUTIA
                             : AArch64::AUTDA;
   EmitToStreamer(MCInstBuilder(AuthOpcode)
-                     .addReg(DstReg)
-                     .addReg(DstReg)
-                     .addReg(AArch64::X16));
+                     .addReg(AuthResultReg)
+                     .addReg(AuthResultReg)
+                     .addReg(AArch64::X17));
 
   if (GAMO.getGlobal()->hasExternalWeakLinkage())
     OutStreamer->emitLabel(UndefWeakSym);
+
+  if (!STI->hasFPAC()) {
+    auto AuthKey =
+        (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA : AArch64PACKey::DA);
+
+    emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
+                                       /*ShouldTrap=*/true,
+                                       /*OnFailure=*/nullptr);
+
+    emitMovXReg(DstReg, AuthResultReg);
+  }
 }
 
 const MCExpr *
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 59ba461d4eb071..fdaa01598dcba5 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1944,8 +1944,8 @@ let Predicates = [HasPAuth] in {
 
   def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>,
                Sched<[WriteI, ReadI]> {
-    let Defs = [X16];
-    let Size = 20;
+    let Defs = [X16,X17,NZCV];
+    let Size = 44;
   }
 
   // Load a signed global address from a special $auth_ptr$ stub slot.
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
index 88cf356214feba..517a0a86ef14bb 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
@@ -1,15 +1,15 @@
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0         -verify-machineinstrs \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0         -verify-machineinstrs \
 ; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
 
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1         -verify-machineinstrs \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1         -verify-machineinstrs \
 ; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
 
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP
 ; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \
 ; RUN:   -relocation-model=pic -mattr=+pauth              %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP
 
@@ -19,10 +19,19 @@
 
 define i32 @get_globalvar() {
 ; CHECK-LABEL: get_globalvar:
-; CHECK:         adrp  x16, :got_auth:var
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
-; CHECK-NEXT:    ldr   x8,  [x16]
-; CHECK-NEXT:    autda x8,  x16
+; CHECK:         adrp  x17, :got_auth:var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var
+; NOTRAP-NEXT:   ldr   x8,  [x17]
+; NOTRAP-NEXT:   autda x8,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:     mov   x8,  x16
 ; CHECK-NEXT:    ldr   w0,  [x8]
 ; CHECK-NEXT:    ret
 
@@ -32,10 +41,19 @@ define i32 @get_globalvar() {
 
 define ptr @get_globalvaraddr() {
 ; CHECK-LABEL: get_globalvaraddr:
-; CHECK:         adrp  x16, :got_auth:var
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
-; CHECK-NEXT:    ldr   x0,  [x16]
-; CHECK-NEXT:    autda x0,  x16
+; CHECK:         adrp  x17, :got_auth:var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autda x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_1:
+; TRAP-NEXT:     mov   x0,  x16
 ; CHECK-NEXT:    ret
 
   %val = load i32, ptr @var
@@ -53,9 +71,9 @@ define ptr @resign_globalfunc() {
 ; TRAP-NEXT:     mov   x17, x16
 ; TRAP-NEXT:     xpaci x17
 ; TRAP-NEXT:     cmp   x16, x17
-; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     b.eq  .Lauth_success_2
 ; TRAP-NEXT:     brk   #0xc470
-; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:   .Lauth_success_2:
 ; CHECK-NEXT:    mov   x17, #42
 ; CHECK-NEXT:    pacia x16, x17
 ; CHECK-NEXT:    mov   x0,  x16
@@ -73,9 +91,9 @@ define ptr @resign_globalvar() {
 ; TRAP-NEXT:     mov   x17, x16
 ; TRAP-NEXT:     xpacd x17
 ; TRAP-NEXT:     cmp   x16, x17
-; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     b.eq  .Lauth_success_3
 ; TRAP-NEXT:     brk   #0xc472
-; TRAP-NEXT:   .Lauth_success_1:
+; TRAP-NEXT:   .Lauth_success_3:
 ; CHECK-NEXT:    mov   x17, #43
 ; CHECK-NEXT:    pacdb x16, x17
 ; CHECK-NEXT:    mov   x0,  x16
@@ -93,9 +111,9 @@ define ptr @resign_globalvar_offset() {
 ; TRAP-NEXT:     mov   x17, x16
 ; TRAP-NEXT:     xpacd x17
 ; TRAP-NEXT:     cmp   x16, x17
-; TRAP-NEXT:     b.eq  .Lauth_success_2
+; TRAP-NEXT:     b.eq  .Lauth_success_4
 ; TRAP-NEXT:     brk   #0xc472
-; TRAP-NEXT:   .Lauth_success_2:
+; TRAP-NEXT:   .Lauth_success_4:
 ; CHECK-NEXT:    add   x16, x16, #16
 ; CHECK-NEXT:    mov   x17, #44
 ; CHECK-NEXT:    pacda x16, x17
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
index 7531df06b99d08..23357cd802574a 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
@@ -1,9 +1,17 @@
 ; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0         -relocation-model=pic -o - %s \
-; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+; RUN:   -mcpu=cyclone -mattr=+pauth -mattr=+fpac | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0         -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth              | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1         -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth -mattr=+fpac | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1         -relocation-model=pic -o - %s \
-; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+; RUN:   -mcpu=cyclone -mattr=+pauth              | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=arm64 -global-isel=1 -global-isel-abort=1 -relocation-model=pic -o - %s \
+; RUN:   -mcpu=cyclone -mattr=+pauth -mattr=+fpac | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=arm64 -global-isel=1 -global-isel-abort=1 -relocation-model=pic -o - %s \
-; RUN:   -mcpu=cyclone -mattr=+pauth | FileCheck %s
+; RUN:   -mcpu=cyclone -mattr=+pauth              | FileCheck --check-prefixes=CHECK,TRAP %s
 
 ;; Note: for FastISel, we fall back to SelectionDAG
 
@@ -15,10 +23,19 @@ define i8 @test_i8(i8 %new) {
   ret i8 %val
 
 ; CHECK-LABEL: test_i8:
-; CHECK:         adrp  x16, :got_auth:var8
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var8
-; CHECK-NEXT:    ldr   x9,  [x16]
-; CHECK-NEXT:    autda x9,  x16
+; CHECK:         adrp  x17, :got_auth:var8
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var8
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:     mov   x9,  x16
 ; CHECK-NEXT:    ldrb  w8,  [x9]
 ; CHECK-NEXT:    strb  w0,  [x9]
 ; CHECK-NEXT:    mov   x0,  x8
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
index bd72b81eeea48e..5d0a3f556c4c2e 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
@@ -1,9 +1,17 @@
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0         -relocation-model=pic \
-; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0         -relocation-model=pic \
+; RUN:   -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1         -relocation-model=pic \
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1         -relocation-model=pic \
-; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
+; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
-; RUN:   -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
 
 ;; Note: for FastISel, we fall back to SelectionDAG
 
@@ -16,12 +24,22 @@ define ptr @foo() {
   ret ptr @var
 
 ; CHECK-LABEL: foo:
-; CHECK:         adrp  x16, :got_auth:var
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:var
-; CHECK-NEXT:    ldr   x0,  [x16]
-; CHECK-NEXT:    cbz   x0, .Lundef_weak0
-; CHECK-NEXT:    autia x0,  x16
+; CHECK:         adrp  x17, :got_auth:var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:var
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   cbz   x0,  .Lundef_weak0
+; NOTRAP-NEXT:   autia x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     cbz   x16, .Lundef_weak0
+; TRAP-NEXT:     autia x16, x17
 ; CHECK-NEXT:  .Lundef_weak0:
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:     mov   x0,  x16
 ; CHECK-NEXT:    ret
 }
 
@@ -32,12 +50,22 @@ define ptr @bar() {
   ret ptr %addr
 
 ; CHECK-LABEL: bar:
-; CHECK:         adrp  x16, :got_auth:arr_var
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:arr_var
-; CHECK-NEXT:    ldr   x8,  [x16]
-; CHECK-NEXT:    cbz   x8, .Lundef_weak1
-; CHECK-NEXT:    autda x8,  x16
+; CHECK:         adrp  x17, :got_auth:arr_var
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:arr_var
+; NOTRAP-NEXT:   ldr   x8,  [x17]
+; NOTRAP-NEXT:   cbz   x8,  .Lundef_weak1
+; NOTRAP-NEXT:   autda x8,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     cbz   x16, .Lundef_weak1
+; TRAP-NEXT:     autda x16, x17
 ; CHECK-NEXT:  .Lundef_weak1:
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_1:
+; TRAP-NEXT:     mov   x8,  x16
 ; CHECK-NEXT:    add   x0,  x8, #20
 ; CHECK-NEXT:    ret
 }
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
index 8a7a48716be2c0..3c4747c3218568 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
@@ -1,9 +1,17 @@
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0         \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0         \
+; RUN:   -relocation-model=pic -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1         \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1         \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \
+; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \
-; RUN:   -relocation-model=pic -mattr=+pauth -mattr=+fpac -o - %s | FileCheck %s
+; RUN:   -relocation-model=pic -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
 
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0         \
 ; RUN:   -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s
@@ -29,22 +37,49 @@ define void @foo() nounwind {
 ; CHECK-LABEL: foo:
 entry:
   call void @consume(i32 ptrtoint (ptr @func to i32))
-; CHECK:         adrp  x16, :got_auth:func
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:func
-; CHECK-NEXT:    ldr   x[[TMP0:[0-9]+]], [x16]
-; CHECK-NEXT:    autia x[[TMP0]], x16
+; CHECK:         adrp  x17, :got_auth:func
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:func
+; NOTRAP-NEXT:   ldr   x[[TMP0:[0-9]+]], [x17]
+; NOTRAP-NEXT:   autia x[[TMP0]], x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:     mov   x[[TMP0:[0-9]+]], x16
 
   call void @consume(i32 ptrtoint (ptr @alias_func to i32))
-; CHECK:         adrp  x16, :got_auth:alias_func
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:alias_func
-; CHECK-NEXT:    ldr   x[[TMP1:[0-9]+]], [x16]
-; CHECK-NEXT:    autia x[[TMP1]], x16
+; CHECK:         adrp  x17, :got_auth:alias_func
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:alias_func
+; NOTRAP-NEXT:   ldr   x[[TMP1:[0-9]+]], [x17]
+; NOTRAP-NEXT:   autia x[[TMP1]], x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_1:
+; TRAP-NEXT:     mov   x[[TMP1:[0-9]+]], x16
 
   call void @consume(i32 ptrtoint (ptr @alias_global to i32))
-; CHECK:         adrp  x16, :got_auth:alias_global
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:alias_global
-; CHECK-NEXT:    ldr   x[[TMP2:[0-9]+]], [x16]
-; CHECK-NEXT:    autda x[[TMP2]], x16
+; CHECK:         adrp  x17, :got_auth:alias_global
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:alias_global
+; NOTRAP-NEXT:   ldr   x[[TMP2:[0-9]+]], [x17]
+; NOTRAP-NEXT:   autda x[[TMP2]], x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_2
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_2:
+; TRAP-NEXT:     mov   x[[TMP2:[0-9]+]], x16
 
   ret void
 }
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
index 9da7044761d648..ee34b439daec7b 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
@@ -1,9 +1,17 @@
 ; RUN: llc -global-isel=0 -fast-isel=0 -O0         --relocation-model=pic < %s \
-; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL,NOTRAP,DAGISEL-NOTRAP
+; RUN: llc -global-isel=0 -fast-isel=0 -O0         --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth              | FileCheck %s --check-prefixes=CHECK,DAGISEL,TRAP,DAGISEL-TRAP
+
+; RUN: llc -global-isel=0 -fast-isel=1 -O0         --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL,NOTRAP,DAGISEL-NOTRAP
 ; RUN: llc -global-isel=0 -fast-isel=1 -O0         --relocation-model=pic < %s \
-; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,DAGISEL
+; RUN:   -mattr=+pauth              | FileCheck %s --check-prefixes=CHECK,DAGISEL,TRAP,DAGISEL-TRAP
+
+; RUN: llc -global-isel=1 -global-isel-abort=1 -O0 --relocation-model=pic < %s \
+; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,GISEL,NOTRAP,GISEL-NOTRAP
 ; RUN: llc -global-isel=1 -global-isel-abort=1 -O0 --relocation-model=pic < %s \
-; RUN:   -mattr=+pauth -mattr=+fpac | FileCheck %s --check-prefixes=CHECK,GISEL
+; RUN:   -mattr=+pauth              | FileCheck %s --check-prefixes=CHECK,GISEL,TRAP,GISEL-TRAP
 
 ;; Note: for FastISel, we fall back to SelectionDAG
 
@@ -15,10 +23,19 @@ declare void @func()
 
 define ptr @global_addr() #0 {
 ; CHECK-LABEL: global_addr:
-; CHECK:         adrp  x16, :got_auth:global
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:global
-; CHECK-NEXT:    ldr   x0,  [x16]
-; CHECK-NEXT:    autda x0,  x16
+; CHECK:         adrp  x17, :got_auth:global
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:global
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autda x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_0
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_0:
+; TRAP-NEXT:     mov   x0,  x16
 ; CHECK-NEXT:    ret
 
   ret ptr @global
@@ -26,10 +43,19 @@ define ptr @global_addr() #0 {
 
 define i32 @global_load() #0 {
 ; CHECK-LABEL: global_load:
-; CHECK:         adrp  x16, :got_auth:global
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:global
-; CHECK-NEXT:    ldr   x8,  [x16]
-; CHECK-NEXT:    autda x8,  x16
+; CHECK:         adrp  x17, :got_auth:global
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:global
+; NOTRAP-NEXT:   ldr   x8,  [x17]
+; NOTRAP-NEXT:   autda x8,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autda x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpacd x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_1
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_1:
+; TRAP-NEXT:     mov   x8,  x16
 ; CHECK-NEXT:    ldr   w0,  [x8]
 ; CHECK-NEXT:    ret
 
@@ -38,27 +64,48 @@ define i32 @global_load() #0 {
 }
 
 define void @global_store() #0 {
-; CHECK-LABEL:   global_store:
-; CHECK:           adrp  x16, :got_auth:global
-; CHECK-NEXT:      add   x16, x16, :got_auth_lo12:global
-; GISEL-NEXT:      ldr   x8,  [x16]
-; GISEL-NEXT:      autda x8,  x16
-; GISEL-NEXT:      str   wzr, [x8]
-; DAGISEL-NEXT:    ldr   x9,  [x16]
-; DAGISEL-NEXT:    autda x9,  x16
-; DAGISEL-NEXT:    mov   w8,  wzr
-; DAGISEL-NEXT:    str   w8,  [x9]
-; CHECK-NEXT:      ret
+; CHECK-LABEL:       global_store:
+; CHECK:               adrp  x17, :got_auth:global
+; CHECK-NEXT:          add   x17, x17, :got_auth_lo12:global
+; GISEL-NOTRAP-NEXT:   ldr   x8,  [x17]
+; GISEL-NOTRAP-NEXT:   autda x8,  x17
+; GISEL-TRAP-NEXT:     ldr   x16, [x17]
+; GISEL-TRAP-NEXT:     autda x16, x17
+; DAGISEL-NOTRAP-NEXT: ldr   x9,  [x17]
+; DAGISEL-NOTRAP-NEXT: autda x9,  x17
+; DAGISEL-TRAP-NEXT:   ldr   x16, [x17]
+; DAGISEL-TRAP-NEXT:   autda x16, x17
+; TRAP-NEXT:           mov   x17, x16
+; TRAP-NEXT:           xpacd x17
+; TRAP-NEXT:           cmp   x16, x17
+; TRAP-NEXT:           b.eq  .Lauth_success_2
+; TRAP-NEXT:           brk   #0xc472
+; TRAP-NEXT:         .Lauth_success_2:
+; GISEL-TRAP-NEXT:     mov   x8,  x16
+; DAGISEL-TRAP-NEXT:   mov   x9,  x16
+; GISEL-NEXT:          str   wzr, [x8]
+; DAGISEL-NEXT:        mov   w8,  wzr
+; DAGISEL-NEXT:        str   w8,  [x9]
+; CHECK-NEXT:          ret
   store i32 0, ptr @global
   ret void
 }
 
 define ptr @func_addr() #0 {
 ; CHECK-LABEL: func_addr:
-; CHECK:         adrp  x16, :got_auth:func
-; CHECK-NEXT:    add   x16, x16, :got_auth_lo12:func
-; CHECK-NEXT:    ldr   x0,  [x16]
-; CHECK-NEXT:    autia x0,  x16
+; CHECK:         adrp  x17, :got_auth:func
+; CHECK-NEXT:    add   x17, x17, :got_auth_lo12:func
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autia x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_3
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_3:
+; TRAP-NEXT:     mov   x0,  x16
 ; CHECK-NEXT:    ret
 
   ret ptr @func



More information about the llvm-commits mailing list