Author: Abhay Kanhere
Date: 2026-02-03T18:03:37+01:00
New Revision: e39d2822bce28c557241bf79fd930fe6dcef840c

URL: 
https://github.com/llvm/llvm-project/commit/e39d2822bce28c557241bf79fd930fe6dcef840c
DIFF: 
https://github.com/llvm/llvm-project/commit/e39d2822bce28c557241bf79fd930fe6dcef840c.diff

LOG: [CodeGen][AArch64] ptrauth intrinsic to safely construct relative ptr 
(#142047)

ptrauth intrinsic to safely construct relative ptr for swift coroutines.

A ptrauth intrinsic for swift co-routine support that allows creation of
signed pointer
 from offset stored at address relative to the pointer.

Following C-like pseudo code (ignoring keys,discriminators) explains its
operation:
      let rawptr = PACauth(inputptr);
return PACsign( rawptr + signextend64( *(int32*)(rawptr+addend) ))

What: Authenticate a signed pointer, load a 32bit value at offset
'addend' from pointer,
       add this value to pointer, sign this new pointer.
 builtin: __builtin_ptrauth_auth_load_relative_and_sign
 intrinsic: ptrauth_auth_resign_load_relative

Added: 
    llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-relative-load.ll

Modified: 
    clang/include/clang/Basic/Builtins.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/lib/Headers/ptrauth.h
    clang/lib/Sema/SemaChecking.cpp
    clang/test/CodeGen/ptrauth-intrinsics.c
    clang/test/Sema/ptrauth.c
    llvm/include/llvm/IR/Intrinsics.td
    llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
    llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
    llvm/lib/Transforms/Utils/Local.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 69699d1f74463..24bb49e245ba9 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4776,6 +4776,12 @@ def PtrauthAuthAndResign : Builtin {
   let Prototype = "void*(void*,int,void*,int,void*)";
 }
 
+def PtrauthAuthLoadRelativeAndSign : Builtin {
+  let Spellings = ["__builtin_ptrauth_auth_load_relative_and_sign"];
+  let Attributes = [CustomTypeChecking, NoThrow];
+  let Prototype = "void*(void*,int,void*,int,void*,ptr
diff _t)";
+}
+
 def PtrauthAuth : Builtin {
   let Spellings = ["__builtin_ptrauth_auth"];
   let Attributes = [CustomTypeChecking, NoThrow];

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 807440c107897..71c478f4ca873 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11317,6 +11317,8 @@ def err_builtin_requires_language : Error<"'%0' is only 
available in %1">;
 
 def err_constant_integer_arg_type : Error<
   "argument to %0 must be a constant integer">;
+def err_constant_integer_last_arg_type
+    : Error<"last argument to %0 must be a constant integer">;
 
 def ext_mixed_decls_code : Extension<
   "mixing declarations and code is a C99 extension">,

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 339d6cff0a386..7f0933d6ceeeb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5712,12 +5712,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const 
GlobalDecl GD, unsigned BuiltinID,
 
   case Builtin::BI__builtin_ptrauth_auth:
   case Builtin::BI__builtin_ptrauth_auth_and_resign:
+  case Builtin::BI__builtin_ptrauth_auth_load_relative_and_sign:
   case Builtin::BI__builtin_ptrauth_blend_discriminator:
   case Builtin::BI__builtin_ptrauth_sign_generic_data:
   case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
   case Builtin::BI__builtin_ptrauth_strip: {
     // Emit the arguments.
-    SmallVector<llvm::Value *, 5> Args;
+    SmallVector<llvm::Value *, 6> Args;
     for (auto argExpr : E->arguments())
       Args.push_back(EmitScalarExpr(argExpr));
 
@@ -5728,6 +5729,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
     switch (BuiltinID) {
     case Builtin::BI__builtin_ptrauth_auth_and_resign:
+    case Builtin::BI__builtin_ptrauth_auth_load_relative_and_sign:
       if (Args[4]->getType()->isPointerTy())
         Args[4] = Builder.CreatePtrToInt(Args[4], IntPtrTy);
       [[fallthrough]];
@@ -5755,6 +5757,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
         return Intrinsic::ptrauth_auth;
       case Builtin::BI__builtin_ptrauth_auth_and_resign:
         return Intrinsic::ptrauth_resign;
+      case Builtin::BI__builtin_ptrauth_auth_load_relative_and_sign:
+        return Intrinsic::ptrauth_resign_load_relative;
       case Builtin::BI__builtin_ptrauth_blend_discriminator:
         return Intrinsic::ptrauth_blend;
       case Builtin::BI__builtin_ptrauth_sign_generic_data:

diff  --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h
index ad28f06f0930c..4650fb4722a8c 100644
--- a/clang/lib/Headers/ptrauth.h
+++ b/clang/lib/Headers/ptrauth.h
@@ -178,6 +178,31 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
   __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, 
\
                                     __new_data)
 
+/* Authenticate a pointer using one scheme, load 32bit value at offset addend
+   from the pointer, and add this value to the pointer, sign using specified
+   scheme.
+
+   If the result is subsequently authenticated using the new scheme, that
+   authentication is guaranteed to fail if and only if the initial
+   authentication failed.
+
+   The value must be an expression of pointer type.
+   The key must be a constant expression of type ptrauth_key.
+   The extra data must be an expression of pointer or integer type;
+   if an integer, it will be coerced to ptrauth_extra_data_t.
+   The addend must be an immediate ptr
diff _t value.
+   The result will have the same type as the original value.
+
+   This operation is guaranteed to not leave the intermediate value
+   available for attack before it is re-signed.
+
+   Do not pass a null pointer to this function. A null pointer
+   will not successfully authenticate. */
+#define ptrauth_auth_load_relative_and_sign(__value, __old_key, __old_data,    
\
+                                            __new_key, __new_data, __offset)   
\
+  __builtin_ptrauth_auth_load_relative_and_sign(                               
\
+      __value, __old_key, __old_data, __new_key, __new_data, __offset)
+
 /* Authenticate a pointer using one scheme and resign it as a C
    function pointer.
 
@@ -363,6 +388,17 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
     __value;                                                                   
\
   })
 
+#define ptrauth_auth_load_relative_and_sign(__value, __old_key, __old_data,    
\
+                                            __new_key, __new_data, __offset)   
\
+  ({                                                                           
\
+    (void)__old_key;                                                           
\
+    (void)__old_data;                                                          
\
+    (void)__new_key;                                                           
\
+    (void)__new_data;                                                          
\
+    const char *__value_tmp = (const char *)(__value);                         
\
+    (void *)(__value_tmp + *(const int *)(__value_tmp + (__offset)));          
\
+  })
+
 #define ptrauth_auth_function(__value, __old_key, __old_data)                  
\
   ({                                                                           
\
     (void)__old_key;                                                           
\

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e2e1b37572364..3f19b6ad16c13 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1839,6 +1839,32 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, 
CallExpr *Call) {
   return Call;
 }
 
+static ExprResult PointerAuthAuthLoadRelativeAndSign(Sema &S, CallExpr *Call) {
+  if (S.checkArgCount(Call, 6))
+    return ExprError();
+  if (checkPointerAuthEnabled(S, Call))
+    return ExprError();
+  const Expr *AddendExpr = Call->getArg(5);
+  bool AddendIsConstInt = AddendExpr->isIntegerConstantExpr(S.Context);
+  if (!AddendIsConstInt) {
+    const Expr *Arg = Call->getArg(5)->IgnoreParenImpCasts();
+    DeclRefExpr *DRE = 
cast<DeclRefExpr>(Call->getCallee()->IgnoreParenCasts());
+    FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+    S.Diag(Arg->getBeginLoc(), diag::err_constant_integer_last_arg_type)
+        << FDecl->getDeclName() << Arg->getSourceRange();
+  }
+  if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_Auth) ||
+      checkPointerAuthKey(S, Call->getArgs()[1]) ||
+      checkPointerAuthValue(S, Call->getArgs()[2], PAO_Discriminator) ||
+      checkPointerAuthKey(S, Call->getArgs()[3]) ||
+      checkPointerAuthValue(S, Call->getArgs()[4], PAO_Discriminator) ||
+      !AddendIsConstInt)
+    return ExprError();
+
+  Call->setType(Call->getArgs()[0]->getType());
+  return Call;
+}
+
 static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) {
   if (checkPointerAuthEnabled(S, Call))
     return ExprError();
@@ -3284,6 +3310,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     return PointerAuthSignGenericData(*this, TheCall);
   case Builtin::BI__builtin_ptrauth_auth_and_resign:
     return PointerAuthAuthAndResign(*this, TheCall);
+  case Builtin::BI__builtin_ptrauth_auth_load_relative_and_sign:
+    return PointerAuthAuthLoadRelativeAndSign(*this, TheCall);
   case Builtin::BI__builtin_ptrauth_string_discriminator:
     return PointerAuthStringDiscriminator(*this, TheCall);
 

diff  --git a/clang/test/CodeGen/ptrauth-intrinsics.c 
b/clang/test/CodeGen/ptrauth-intrinsics.c
index 50bf1898e4b37..bd348f9b3551a 100644
--- a/clang/test/CodeGen/ptrauth-intrinsics.c
+++ b/clang/test/CodeGen/ptrauth-intrinsics.c
@@ -55,6 +55,18 @@ void test_auth_and_resign() {
   fnptr = __builtin_ptrauth_auth_and_resign(fnptr, 0, ptr_discriminator, 3, 
15);
 }
 
+// CHECK-LABEL: define {{.*}}void @test_auth_load_relative_and_sign()
+void test_auth_load_relative_and_sign() {
+  // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
+  // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator,
+  // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64
+  // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64
+  // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign.load.relative(i64 
[[T0]], i32 0, i64 [[DISC]], i32 3, i64 15, i64  16)
+  // CHECK-NEXT: [[RESULT:%.*]] = inttoptr  i64 [[T1]] to ptr
+  // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr,
+  fnptr = __builtin_ptrauth_auth_load_relative_and_sign(fnptr, 0, 
ptr_discriminator, 3, 15, 16L);
+}
+
 // CHECK-LABEL: define {{.*}}void @test_blend_discriminator()
 void test_blend_discriminator() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,

diff  --git a/clang/test/Sema/ptrauth.c b/clang/test/Sema/ptrauth.c
index 6c4b92b0104df..59c18a3ef5e40 100644
--- a/clang/test/Sema/ptrauth.c
+++ b/clang/test/Sema/ptrauth.c
@@ -121,6 +121,29 @@ void test_auth_and_resign(int *dp, int (*fp)(int)) {
 
   float *mismatch = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, 
VALID_DATA_KEY, dp); // expected-error {{incompatible pointer types 
initializing 'float *' with an expression of type 'int *'}}
 }
+void test_auth_load_relative_and_sign(int *dp, int (*fp)(int)) {
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 0, 
VALID_DATA_KEY, 0); // expected-error {{too few arguments}}
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, dp, 
VALID_DATA_KEY, dp, 0, 0); // expected-error {{too many arguments}}
+  int n = *dp;
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, dp, 
VALID_DATA_KEY, dp,n); // expected-error {{last argument to 
'__builtin_ptrauth_auth_load_relative_and_sign' must be a constant integer}}
+  __builtin_ptrauth_auth_load_relative_and_sign(mismatched_type, 
VALID_DATA_KEY, 0, VALID_DATA_KEY, dp, 0); // expected-error {{signed value 
must have pointer type; type here is 'struct A'}}
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, mismatched_type, 0, 
VALID_DATA_KEY, dp, 0); // expected-error {{passing 'struct A' to parameter of 
incompatible type 'int'}}
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 
mismatched_type, VALID_DATA_KEY, dp, 0); // expected-error {{extra 
discriminator must have pointer or integer type; type here is 'struct A'}}
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 0, 
mismatched_type, dp, 0); // expected-error {{passing 'struct A' to parameter of 
incompatible type 'int'}}
+  __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 0, 
VALID_DATA_KEY, mismatched_type, 0); // expected-error {{extra discriminator 
must have pointer or integer type; type here is 'struct A'}}
+
+  (void) __builtin_ptrauth_auth_and_resign(NULL, VALID_DATA_KEY, 0, 
VALID_DATA_KEY, dp); // expected-warning {{authenticating a null pointer will 
almost certainly trap}}
+
+  int *dr = __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 
0, VALID_DATA_KEY, dp, 10);
+  dr = __builtin_ptrauth_auth_load_relative_and_sign(dp, INVALID_KEY, 0, 
VALID_DATA_KEY, dp, 10); // expected-error {{does not identify a valid pointer 
authentication key for the current target}}
+  dr = __builtin_ptrauth_auth_load_relative_and_sign(dp, VALID_DATA_KEY, 0, 
INVALID_KEY, dp, 10); // expected-error {{does not identify a valid pointer 
authentication key for the current target}}
+
+  int (*fr)(int) = __builtin_ptrauth_auth_load_relative_and_sign(fp, 
VALID_CODE_KEY, 0, VALID_CODE_KEY, dp, 10);
+  fr = __builtin_ptrauth_auth_load_relative_and_sign(fp, INVALID_KEY, 0, 
VALID_CODE_KEY, dp, 10); // expected-error {{does not identify a valid pointer 
authentication key for the current target}}
+  fr = __builtin_ptrauth_auth_load_relative_and_sign(fp, VALID_CODE_KEY, 0, 
INVALID_KEY, dp, 10); // expected-error {{does not identify a valid pointer 
authentication key for the current target}}
+
+  float *mismatch = __builtin_ptrauth_auth_load_relative_and_sign(dp, 
VALID_DATA_KEY, 0, VALID_DATA_KEY, dp,0); // expected-error {{incompatible 
pointer types initializing 'float *' with an expression of type 'int *'}}
+}
 
 void test_sign_generic_data(int *dp) {
   __builtin_ptrauth_sign_generic_data(dp); // expected-error {{too few 
arguments}}

diff  --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index ea6bd59c5aeca..ab5f3fbbaf860 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -2924,6 +2924,19 @@ def int_ptrauth_resign : Intrinsic<[llvm_i64_ty],
                                    [IntrNoMem, ImmArg<ArgIndex<1>>,
                                     ImmArg<ArgIndex<3>>]>;
 
+// Authenticate a signed pointer, load 32bit value at offset from pointer, add
+// both, and sign it. The second (key) and third (discriminator) arguments
+// specify the signing schema used for authenticating. The fourth and fifth
+// arguments specify the schema used for signing. The sixth argument is addend
+// added to pointer to load the relative offset. The signature must be valid.
+// This is a combined form of int_ptrauth_resign for relative pointers
+def int_ptrauth_resign_load_relative
+    : Intrinsic<[llvm_i64_ty],
+                [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i32_ty,
+                 llvm_i64_ty, llvm_i64_ty],
+                [IntrReadMem, ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<3>>,
+                 ImmArg<ArgIndex<5>>]>;
+
 // Strip the embedded signature out of a signed pointer.
 // The second argument specifies the key.
 // This behaves like @llvm.ptrauth.auth, but doesn't require the signature to

diff  --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp 
b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 57867fc8afb7d..2b8db27599d3c 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -199,11 +199,11 @@ class AArch64AsmPrinter : public AsmPrinter {
     bool AddrDiscIsKilled;
   };
 
-  // Emit the sequence for AUT or AUTPAC.
+  // Emit the sequence for AUT or AUTPAC. Addend if AUTRELLOADPAC
   void emitPtrauthAuthResign(Register Pointer, Register Scratch,
                              PtrAuthSchema AuthSchema,
                              std::optional<PtrAuthSchema> SignSchema,
-                             Value *DS);
+                             std::optional<uint64_t> Addend, Value *DS);
 
   // Emit R_AARCH64_PATCHINST, the deactivation symbol relocation. Returns true
   // if no instruction should be emitted because the deactivation symbol is
@@ -2237,9 +2237,10 @@ AArch64AsmPrinter::PtrAuthSchema::PtrAuthSchema(
 
 void AArch64AsmPrinter::emitPtrauthAuthResign(
     Register Pointer, Register Scratch, PtrAuthSchema AuthSchema,
-    std::optional<PtrAuthSchema> SignSchema, Value *DS) {
+    std::optional<PtrAuthSchema> SignSchema, std::optional<uint64_t> OptAddend,
+    Value *DS) {
   const bool IsResign = SignSchema.has_value();
-
+  const bool HasLoad = OptAddend.has_value();
   // We expand AUT/AUTPAC into a sequence of the form
   //
   //      ; authenticate x16
@@ -2301,12 +2302,76 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(
   }
 
   // We already emitted unchecked and checked-but-non-trapping AUTs.
-  // That left us with trapping AUTs, and AUTPACs.
+  // That left us with trapping AUTs, and AUTPA/AUTRELLOADPACs.
   // Trapping AUTs don't need PAC: we're done.
   if (!IsResign)
     return;
 
-  // Compute pac discriminator
+  if (HasLoad) {
+    int64_t Addend = *OptAddend;
+    // incoming rawpointer in X16, X17 is not live at this point.
+    //   LDSRWpre x17, x16, simm9  ; note: x16+simm9 used later.
+    if (isInt<9>(Addend)) {
+      EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWpre)
+                                       .addReg(AArch64::X16)
+                                       .addReg(AArch64::X17)
+                                       .addReg(AArch64::X16)
+                                       .addImm(/*simm9:*/ Addend));
+    } else {
+      //   x16 = x16 + Addend computation has 2 variants
+      if (isUInt<24>(Addend)) {
+        // variant 1: add x16, x16, Addend >> shift12 ls shift12
+        // This can take upto 2 instructions.
+        for (int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) 
{
+          EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
+                                           .addReg(AArch64::X16)
+                                           .addReg(AArch64::X16)
+                                           .addImm((Addend >> BitPos) & 0xfff)
+                                           .addImm(AArch64_AM::getShifterImm(
+                                               AArch64_AM::LSL, BitPos)));
+        }
+      } else {
+        // variant 2: accumulate constant in X17 16 bits at a time, and add to
+        // X16 This can take 2-5 instructions.
+        EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi)
+                                         .addReg(AArch64::X17)
+                                         .addImm(Addend & 0xffff)
+                                         .addImm(AArch64_AM::getShifterImm(
+                                             AArch64_AM::LSL, 0)));
+
+        for (int Offset = 16; Offset < 64; Offset += 16) {
+          uint16_t Fragment = static_cast<uint16_t>(Addend >> Offset);
+          if (!Fragment)
+            continue;
+          EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi)
+                                           .addReg(AArch64::X17)
+                                           .addReg(AArch64::X17)
+                                           .addImm(Fragment)
+                                           .addImm(/*shift:*/ Offset));
+        }
+        // addx x16, x16, x17
+        EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
+                                         .addReg(AArch64::X16)
+                                         .addReg(AArch64::X16)
+                                         .addReg(AArch64::X17)
+                                         .addImm(0));
+      }
+      // ldrsw x17,x16(0)
+      EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWui)
+                                       .addReg(AArch64::X17)
+                                       .addReg(AArch64::X16)
+                                       .addImm(0));
+    }
+    // addx x16, x16, x17
+    EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
+                                     .addReg(AArch64::X16)
+                                     .addReg(AArch64::X16)
+                                     .addReg(AArch64::X17)
+                                     .addImm(0));
+
+  } /* HasLoad == true */
+
+  // Compute pac discriminator into x17
   Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
                                                  SignSchema->AddrDisc, 
Scratch);
   emitPAC(SignSchema->Key, Pointer, PACDiscReg);
@@ -3221,7 +3286,7 @@ void AArch64AsmPrinter::emitInstruction(const 
MachineInstr *MI) {
                              MI->getOperand(1).getImm(), MI->getOperand(2));
 
     emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
-                          MI->getDeactivationSymbol());
+                          std::nullopt, MI->getDeactivationSymbol());
     return;
   }
 
@@ -3233,7 +3298,7 @@ void AArch64AsmPrinter::emitInstruction(const 
MachineInstr *MI) {
                              MI->getOperand(4).getImm(), MI->getOperand(5));
 
     emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
-                          MI->getDeactivationSymbol());
+                          std::nullopt, MI->getDeactivationSymbol());
     return;
   }
 
@@ -3248,7 +3313,24 @@ void AArch64AsmPrinter::emitInstruction(const 
MachineInstr *MI) {
                              MI->getOperand(4).getImm(), MI->getOperand(5));
 
     emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
+                          std::nullopt, MI->getDeactivationSymbol());
+    return;
+  }
+
+  case AArch64::AUTRELLOADPAC: {
+    const Register Pointer = AArch64::X16;
+    const Register Scratch = AArch64::X17;
+
+    PtrAuthSchema AuthSchema((AArch64PACKey::ID)MI->getOperand(0).getImm(),
+                             MI->getOperand(1).getImm(), MI->getOperand(2));
+
+    PtrAuthSchema SignSchema((AArch64PACKey::ID)MI->getOperand(3).getImm(),
+                             MI->getOperand(4).getImm(), MI->getOperand(5));
+
+    emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
+                          MI->getOperand(6).getImm(),
                           MI->getDeactivationSymbol());
+
     return;
   }
 

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index a8ec446d90ac2..0fb2b6493e061 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -1582,12 +1582,15 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) {
 
 void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) {
   SDLoc DL(N);
-  // IntrinsicID is operand #0
-  SDValue Val = N->getOperand(1);
-  SDValue AUTKey = N->getOperand(2);
-  SDValue AUTDisc = N->getOperand(3);
-  SDValue PACKey = N->getOperand(4);
-  SDValue PACDisc = N->getOperand(5);
+  // IntrinsicID is operand #0, if W_CHAIN it is #1
+  int OffsetBase = N->getOpcode() == ISD::INTRINSIC_W_CHAIN ? 1 : 0;
+  SDValue Val = N->getOperand(OffsetBase + 1);
+  SDValue AUTKey = N->getOperand(OffsetBase + 2);
+  SDValue AUTDisc = N->getOperand(OffsetBase + 3);
+  SDValue PACKey = N->getOperand(OffsetBase + 4);
+  SDValue PACDisc = N->getOperand(OffsetBase + 5);
+  uint32_t IntNum = N->getConstantOperandVal(OffsetBase + 0);
+  bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
 
   unsigned AUTKeyC = cast<ConstantSDNode>(AUTKey)->getZExtValue();
   unsigned PACKeyC = cast<ConstantSDNode>(PACKey)->getZExtValue();
@@ -1606,11 +1609,23 @@ void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode 
*N) {
   SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL,
                                          AArch64::X16, Val, SDValue());
 
-  SDValue Ops[] = {AUTKey,       AUTConstDisc, AUTAddrDisc,        PACKey,
-                   PACConstDisc, PACAddrDisc,  X16Copy.getValue(1)};
+  if (HasLoad) {
+    SDValue Addend = N->getOperand(OffsetBase + 6);
+    SDValue IncomingChain = N->getOperand(0);
+    SDValue Ops[] = {AUTKey, AUTConstDisc,  AUTAddrDisc,
+                     PACKey, PACConstDisc,  PACAddrDisc,
+                     Addend, IncomingChain, X16Copy.getValue(1)};
 
-  SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops);
-  ReplaceNode(N, AUTPAC);
+    SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC, DL,
+                                                   MVT::i64, MVT::Other, Ops);
+    ReplaceNode(N, AUTRELLOADPAC);
+  } else {
+    SDValue Ops[] = {AUTKey,       AUTConstDisc, AUTAddrDisc,        PACKey,
+                     PACConstDisc, PACAddrDisc,  X16Copy.getValue(1)};
+
+    SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, 
Ops);
+    ReplaceNode(N, AUTPAC);
+  }
 }
 
 bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) {
@@ -5836,6 +5851,9 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
               {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
         SelectCVTIntrinsicFP8(Node, 2, Opc);
       return;
+    case Intrinsic::ptrauth_resign_load_relative:
+      SelectPtrauthResign(Node);
+      return;
     }
   } break;
   case ISD::INTRINSIC_WO_CHAIN: {

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td 
b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 4420f8f91ee46..ba32eac2f0d28 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2275,6 +2275,26 @@ let Predicates = [HasPAuth] in {
     let Uses = [X16];
   }
 
+  // Similiar to AUTPAC, except a 32bit value is loaded at Addend offset from
+  // pointer and this value is added to the pointer before signing. This
+  // directly manipulates x16/x17, which are the only registers the OS
+  // guarantees are safe to use for sensitive operations.
+  def AUTRELLOADPAC
+      : Pseudo<(outs),
+               (ins i32imm:$AUTKey, i64imm:$AUTDisc, GPR64:$AUTAddrDisc,
+                   i32imm:$PACKey, i64imm:$PACDisc, GPR64noip:$PACAddrDisc,
+                   i64imm:$Addend),
+               []>,
+        Sched<[WriteI, ReadI]> {
+    let isCodeGenOnly = 1;
+    let hasSideEffects = 1;
+    let mayStore = 0;
+    let mayLoad = 1;
+    let Size = 84;
+    let Defs = [X16, X17, NZCV];
+    let Uses = [X16];
+  }
+
   // Materialize a signed global address, with adrp+add and PAC.
   def MOVaddrPAC : Pseudo<(outs),
                           (ins i64imm:$Addr, i32imm:$Key,

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index b05da9376d966..1f1592caf0a8a 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -6613,6 +6613,42 @@ bool 
AArch64InstructionSelector::selectIntrinsicWithSideEffects(
     constrainSelectedInstRegOperands(*Memset, TII, TRI, RBI);
     break;
   }
+  case Intrinsic::ptrauth_resign_load_relative: {
+    Register DstReg = I.getOperand(0).getReg();
+    Register ValReg = I.getOperand(2).getReg();
+    uint64_t AUTKey = I.getOperand(3).getImm();
+    Register AUTDisc = I.getOperand(4).getReg();
+    uint64_t PACKey = I.getOperand(5).getImm();
+    Register PACDisc = I.getOperand(6).getReg();
+    int64_t Addend = I.getOperand(7).getImm();
+
+    Register AUTAddrDisc = AUTDisc;
+    uint16_t AUTConstDiscC = 0;
+    std::tie(AUTConstDiscC, AUTAddrDisc) =
+        extractPtrauthBlendDiscriminators(AUTDisc, MRI);
+
+    Register PACAddrDisc = PACDisc;
+    uint16_t PACConstDiscC = 0;
+    std::tie(PACConstDiscC, PACAddrDisc) =
+        extractPtrauthBlendDiscriminators(PACDisc, MRI);
+
+    MIB.buildCopy({AArch64::X16}, {ValReg});
+
+    MIB.buildInstr(AArch64::AUTRELLOADPAC)
+        .addImm(AUTKey)
+        .addImm(AUTConstDiscC)
+        .addUse(AUTAddrDisc)
+        .addImm(PACKey)
+        .addImm(PACConstDiscC)
+        .addUse(PACAddrDisc)
+        .addImm(Addend)
+        .constrainAllUses(TII, TRI, RBI);
+    MIB.buildCopy({DstReg}, Register(AArch64::X16));
+
+    RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
+    I.eraseFromParent();
+    return true;
+  }
   }
 
   I.eraseFromParent();

diff  --git a/llvm/lib/Transforms/Utils/Local.cpp 
b/llvm/lib/Transforms/Utils/Local.cpp
index 9b9516da9c552..aa52003e8dfe1 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -457,6 +457,7 @@ bool llvm::wouldInstructionBeTriviallyDead(const 
Instruction *I,
     case Intrinsic::wasm_trunc_unsigned:
     case Intrinsic::ptrauth_auth:
     case Intrinsic::ptrauth_resign:
+    case Intrinsic::ptrauth_resign_load_relative:
       return true;
     default:
       return false;

diff  --git 
a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-relative-load.ll 
b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-relative-load.ll
new file mode 100644
index 0000000000000..2baa72b9a0107
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-relative-load.ll
@@ -0,0 +1,570 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0                    
-verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" 
--check-prefix=UNCHECKED
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 
-verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" 
--check-prefix=UNCHECKED
+
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0                    
-verify-machineinstrs \
+; RUN:                                     | FileCheck %s -DL="L" 
--check-prefix=CHECKED
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 
-verify-machineinstrs \
+; RUN:                                     | FileCheck %s -DL="L" 
--check-prefix=CHECKED
+
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0                    
-verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" 
--check-prefix=TRAP
+; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 
-verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" 
--check-prefix=TRAP
+
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0        
            -verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" 
--check-prefix=UNCHECKED
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel 
-global-isel-abort=1 -verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" 
--check-prefix=UNCHECKED
+
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0        
            -verify-machineinstrs \
+; RUN:                                     | FileCheck %s -DL=".L" 
--check-prefix=CHECKED
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel 
-global-isel-abort=1 -verify-machineinstrs \
+; RUN:                                     | FileCheck %s -DL=".L" 
--check-prefix=CHECKED
+
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0        
            -verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" 
--check-prefix=TRAP
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel 
-global-isel-abort=1 -verify-machineinstrs \
+; RUN:   -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" 
--check-prefix=TRAP
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+define i64 @test_resign_load_relative_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_ia_ia:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autia x16, x1
+; UNCHECKED-NEXT:    ldrsw x17, [x16, #-256]!
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacia x16, x2
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_ia_ia:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autia x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpaci x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_0
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_0
+; CHECKED-NEXT:  Lauth_success_0:
+; CHECKED-NEXT:    ldrsw x17, [x16, #-256]!
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacia x16, x2
+; CHECKED-NEXT:  Lresign_end_0:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_ia_ia:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autia x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpaci x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_0
+; TRAP-NEXT:    brk #0xc470
+; TRAP-NEXT:  Lauth_success_0:
+; TRAP-NEXT:    ldrsw x17, [x16, #-256]!
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacia x16, x2
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 0, i64 
%arg1, i32 0, i64 %arg2, i64 -256)
+  ret i64 %tmp
+}
+
+; note: offset 256 is larger tha 255 (largest simm9), is uint<24>
+define i64 @test_resign_load_relative_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_ib_ia:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autib x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacia x16, x2
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_ib_ia:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autib x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpaci x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_1
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_1
+; CHECKED-NEXT:  Lauth_success_1:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacia x16, x2
+; CHECKED-NEXT:  Lresign_end_1:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_ib_ia:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autib x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpaci x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_1
+; TRAP-NEXT:    brk #0xc471
+; TRAP-NEXT:  Lauth_success_1:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacia x16, x2
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 1, i64 
%arg1, i32 0, i64 %arg2, i64 256)
+  ret i64 %tmp
+}
+
+define i64 @test_resign_load_relative_da_ia(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_da_ia:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autda x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacia x16, x2
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_da_ia:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autda x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_2
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_2
+; CHECKED-NEXT:  Lauth_success_2:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacia x16, x2
+; CHECKED-NEXT:  Lresign_end_2:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_da_ia:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autda x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_2
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_2:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacia x16, x2
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 2, i64 
%arg1, i32 0, i64 %arg2, i64 256)
+  ret i64 %tmp
+}
+
+define i64 @test_resign_load_relative_db_da(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_db_da:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autdb x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacda x16, x2
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_db_da:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autdb x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_3
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_3
+; CHECKED-NEXT:  Lauth_success_3:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacda x16, x2
+; CHECKED-NEXT:  Lresign_end_3:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_db_da:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autdb x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_3
+; TRAP-NEXT:    brk #0xc473
+; TRAP-NEXT:  Lauth_success_3:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacda x16, x2
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 3, i64 
%arg1, i32 2, i64 %arg2, i64 256)
+  ret i64 %tmp
+}
+
+define i64 @test_resign_load_relative_iza_db(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_iza_db:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autiza x16
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacdb x16, x2
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_iza_db:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autiza x16
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpaci x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_4
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_4
+; CHECKED-NEXT:  Lauth_success_4:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacdb x16, x2
+; CHECKED-NEXT:  Lresign_end_4:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_iza_db:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autiza x16
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpaci x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_4
+; TRAP-NEXT:    brk #0xc470
+; TRAP-NEXT:  Lauth_success_4:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacdb x16, x2
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 0, i64 0, 
i32 3, i64 %arg2, i64 256)
+  ret i64 %tmp
+}
+
+define i64 @test_resign_load_relative_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) {
+; UNCHECKED-LABEL: test_resign_load_relative_da_dzb:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autda x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    pacdzb x16
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_da_dzb:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autda x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_5
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_5
+; CHECKED-NEXT:  Lauth_success_5:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    pacdzb x16
+; CHECKED-NEXT:  Lresign_end_5:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_da_dzb:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autda x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_5
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_5:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    pacdzb x16
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 2, i64 
%arg1, i32 3, i64 0,i64 256)
+  ret i64 %tmp
+}
+
+define i64 @test_resign_load_relative_da_constdisc(i64 %arg, i64 %arg1) {
+; UNCHECKED-LABEL: test_resign_load_relative_da_constdisc:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autda x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #256
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    mov x17, #256 
+; UNCHECKED-NEXT:    pacda x16, x17
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_da_constdisc:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autda x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_6
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_6
+; CHECKED-NEXT:  Lauth_success_6:
+; CHECKED-NEXT:    add x16, x16, #256
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    mov x17, #256 
+; CHECKED-NEXT:    pacda x16, x17
+; CHECKED-NEXT:  Lresign_end_6:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_da_constdisc:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autda x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_6
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_6:
+; TRAP-NEXT:    add x16, x16, #256
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    mov x17, #256 
+; TRAP-NEXT:    pacda x16, x17
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg, i32 2, i64 
%arg1, i32 2, i64 256,i64 256)
+  ret i64 %tmp
+}
+
+; note: addend is larger than 24bit integer
+define i64 @test_resign_load_relative_loadNegOffset_constdisc(i64 %arg,i64 
%arg1) {
+; UNCHECKED-LABEL: test_resign_load_relative_loadNegOffset_constdisc:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autda x16, x1
+; UNCHECKED-NEXT:    mov x17, #62980 
+; UNCHECKED-NEXT:    movk x17, #65535, lsl #16
+; UNCHECKED-NEXT:    movk x17, #65535, lsl #32
+; UNCHECKED-NEXT:    movk x17, #65535, lsl #48
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    mov x17, #256 
+; UNCHECKED-NEXT:    pacda x16, x17
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_loadNegOffset_constdisc:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autda x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_7
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_7
+; CHECKED-NEXT:  Lauth_success_7:
+; CHECKED-NEXT:    mov x17, #62980 
+; CHECKED-NEXT:    movk x17, #65535, lsl #16
+; CHECKED-NEXT:    movk x17, #65535, lsl #32
+; CHECKED-NEXT:    movk x17, #65535, lsl #48
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    mov x17, #256 
+; CHECKED-NEXT:    pacda x16, x17
+; CHECKED-NEXT:  Lresign_end_7:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_loadNegOffset_constdisc:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autda x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_7
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_7:
+; TRAP-NEXT:    mov x17, #62980
+; TRAP-NEXT:    movk x17, #65535, lsl #16
+; TRAP-NEXT:    movk x17, #65535, lsl #32
+; TRAP-NEXT:    movk x17, #65535, lsl #48
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    mov x17, #256 
+; TRAP-NEXT:    pacda x16, x17
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg,i32 2,i64 
%arg1,i32 2,i64 256,i64 -2556)
+  ret i64 %tmp
+}
+define i64 @test_resign_load_relative_largeOffset_constdisc(i64 %arg,i64 
%arg1) {
+; UNCHECKED-LABEL: test_resign_load_relative_largeOffset_constdisc:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    mov x16, x0
+; UNCHECKED-NEXT:    autda x16, x1
+; UNCHECKED-NEXT:    add x16, x16, #3884
+; UNCHECKED-NEXT:    add x16, x16, #7, lsl #12
+; UNCHECKED-NEXT:    ldrsw x17, [x16]
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    mov x17, #256 
+; UNCHECKED-NEXT:    pacda x16, x17
+; UNCHECKED-NEXT:    mov x0, x16
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_resign_load_relative_largeOffset_constdisc:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    mov x16, x0
+; CHECKED-NEXT:    autda x16, x1
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_8
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_8
+; CHECKED-NEXT:  Lauth_success_8:
+; CHECKED-NEXT:    add x16, x16, #3884
+; CHECKED-NEXT:    add x16, x16, #7, lsl #12 
+; CHECKED-NEXT:    ldrsw x17, [x16]
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    mov x17, #256 
+; CHECKED-NEXT:    pacda x16, x17
+; CHECKED-NEXT:  Lresign_end_8:
+; CHECKED-NEXT:    mov x0, x16
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_resign_load_relative_largeOffset_constdisc:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    mov x16, x0
+; TRAP-NEXT:    autda x16, x1
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_8
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_8:
+; TRAP-NEXT:    add x16, x16, #3884
+; TRAP-NEXT:    add x16, x16, #7, lsl #12 
+; TRAP-NEXT:    ldrsw x17, [x16]
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    mov x17, #256 
+; TRAP-NEXT:    pacda x16, x17
+; TRAP-NEXT:    mov x0, x16
+; TRAP-NEXT:    ret
+  %tmp = call i64 @llvm.ptrauth.resign.load.relative(i64 %arg,i32 2,i64 
%arg1,i32 2,i64 256,i64 32556)
+  ret i64 %tmp
+}
+define void  @test_intrinsic_glue_chain_correctly_setup(ptr %0, i64 %1, ptr 
%2)  {
+; UNCHECKED-LABEL: test_intrinsic_glue_chain_correctly_setup:
+; UNCHECKED:         %bb.0:
+; UNCHECKED-NEXT:    str x2, [x0]
+; UNCHECKED-NEXT:    mov x16, x1
+; UNCHECKED-NEXT:    mov x17, #29199
+; UNCHECKED-NEXT:    autda x16, x17
+; UNCHECKED-NEXT:    ldrsw x17, [x16, #0]!
+; UNCHECKED-NEXT:    add x16, x16, x17
+; UNCHECKED-NEXT:    mov x17, #29199
+; UNCHECKED-NEXT:    pacia x16, x17
+; UNCHECKED-NEXT:    ret
+;
+; CHECKED-LABEL: test_intrinsic_glue_chain_correctly_setup:
+; CHECKED:         %bb.0:
+; CHECKED-NEXT:    str x2, [x0]
+; CHECKED-NEXT:    mov x16, x1
+; CHECKED-NEXT:    mov x17, #29199
+; CHECKED-NEXT:    autda x16, x17
+; CHECKED-NEXT:    mov x17, x16
+; CHECKED-NEXT:    xpacd x17
+; CHECKED-NEXT:    cmp x16, x17
+; CHECKED-NEXT:    b.eq [[L]]auth_success_9
+; CHECKED-NEXT:    mov x16, x17
+; CHECKED-NEXT:    b [[L]]resign_end_9
+; CHECKED-NEXT:  Lauth_success_9:
+; CHECKED-NEXT:    ldrsw x17, [x16, #0]!
+; CHECKED-NEXT:    add x16, x16, x17
+; CHECKED-NEXT:    mov x17, #29199
+; CHECKED-NEXT:    pacia x16, x17
+; CHECKED-NEXT:  Lresign_end_9:
+; CHECKED-NEXT:    ret
+;
+; TRAP-LABEL: test_intrinsic_glue_chain_correctly_setup:
+; TRAP:         %bb.0:
+; TRAP-NEXT:    str x2, [x0]
+; TRAP-NEXT:    mov x16, x1
+; TRAP-NEXT:    mov x17, #29199
+; TRAP-NEXT:    autda x16, x17
+; TRAP-NEXT:    mov x17, x16
+; TRAP-NEXT:    xpacd x17
+; TRAP-NEXT:    cmp x16, x17
+; TRAP-NEXT:    b.eq [[L]]auth_success_9
+; TRAP-NEXT:    brk #0xc472
+; TRAP-NEXT:  Lauth_success_9:
+; TRAP-NEXT:    ldrsw x17, [x16, #0]!
+; TRAP-NEXT:    add x16, x16, x17
+; TRAP-NEXT:    mov x17, #29199
+; TRAP-NEXT:    pacia x16, x17
+; TRAP-NEXT:    ret
+  store ptr %2, ptr %0, align 8
+  %15 = tail call i64 @llvm.ptrauth.resign.load.relative(i64 %1, i32 2, i64 
29199, i32 0, i64 29199, i64 0)
+  ret void
+}
+declare i64 @llvm.ptrauth.auth(i64, i32, i64)
+declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)
+declare i64 @llvm.ptrauth.resign.load.relative(i64,i32,i64,i32,i64,i64)


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to