[llvm] [InstCombine] Combine ptrauth intrin. callee into same-key bundle. (PR #94707)

Ahmed Bougacha via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 15 11:49:06 PDT 2025


https://github.com/ahmedbougacha updated https://github.com/llvm/llvm-project/pull/94707

>From e623f4813a7338c6ef5f3c0a825a02f83bde5887 Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 31 Jul 2023 07:22:40 -0700
Subject: [PATCH 1/4] [InstCombine] Combine ptrauth intrin. callee into
 same-key bundle.

Try to optimize a call to the result of a ptrauth intrinsic, potentially
into the ptrauth call bundle:
- call(ptrauth.resign(p)), ["ptrauth"()] ->  call p, ["ptrauth"()]
- call(ptrauth.sign(p)),   ["ptrauth"()] ->  call p
as long as the key/discriminator are the same in sign and auth-bundle,
and we don't change the key in the bundle (to a potentially-invalid
key.)

Generating a plain call to a raw unauthenticated pointer is generally
undesirable, but if we ended up seeing a naked ptrauth.sign in the first
place, we already have suspicious code.  Unauthenticated calls are also
easier to spot than naked signs, so let the indirect call shine.
---
 .../InstCombine/InstCombineCalls.cpp          | 76 +++++++++++++++++++
 .../InstCombine/InstCombineInternal.h         |  8 ++
 .../InstCombine/ptrauth-intrinsics-call.ll    | 76 +++++++++++++++++++
 3 files changed, 160 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 436cdbff75669..8c32f411320ab 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3665,6 +3665,78 @@ static IntrinsicInst *findInitTrampoline(Value *Callee) {
   return nullptr;
 }
 
+Instruction *InstCombinerImpl::foldPtrAuthIntrinsicCallee(CallBase &Call) {
+  Value *Callee = Call.getCalledOperand();
+  auto *IPC = dyn_cast<IntToPtrInst>(Callee);
+  if (!IPC || !IPC->isNoopCast(DL))
+    return nullptr;
+
+  IntrinsicInst *II = dyn_cast<IntrinsicInst>(IPC->getOperand(0));
+  if (!II)
+    return nullptr;
+
+  // Isolate the ptrauth bundle from the others.
+  std::optional<OperandBundleUse> PtrAuthBundleOrNone;
+  SmallVector<OperandBundleDef, 2> NewBundles;
+  for (unsigned BI = 0, BE = Call.getNumOperandBundles(); BI != BE; ++BI) {
+    OperandBundleUse Bundle = Call.getOperandBundleAt(BI);
+    if (Bundle.getTagID() == LLVMContext::OB_ptrauth)
+      PtrAuthBundleOrNone = Bundle;
+    else
+      NewBundles.emplace_back(Bundle);
+  }
+
+  Value *NewCallee = nullptr;
+  switch (II->getIntrinsicID()) {
+  default:
+    return nullptr;
+
+  // call(ptrauth.resign(p)), ["ptrauth"()] ->  call p, ["ptrauth"()]
+  // assuming the call bundle and the sign operands match.
+  case Intrinsic::ptrauth_resign: {
+    if (!PtrAuthBundleOrNone ||
+        II->getOperand(3) != PtrAuthBundleOrNone->Inputs[0] ||
+        II->getOperand(4) != PtrAuthBundleOrNone->Inputs[1])
+      return nullptr;
+
+    // Don't change the key used in the call; we don't know what's valid.
+    if (II->getOperand(1) != PtrAuthBundleOrNone->Inputs[0])
+      return nullptr;
+
+    Value *NewBundleOps[] = {II->getOperand(1), II->getOperand(2)};
+    NewBundles.emplace_back("ptrauth", NewBundleOps);
+    NewCallee = II->getOperand(0);
+    break;
+  }
+
+  // call(ptrauth.sign(p)), ["ptrauth"()] ->  call p
+  // assuming the call bundle and the sign operands match.
+  // Non-ptrauth indirect calls are undesirable, but so is ptrauth.sign.
+  case Intrinsic::ptrauth_sign: {
+    if (!PtrAuthBundleOrNone ||
+        II->getOperand(1) != PtrAuthBundleOrNone->Inputs[0] ||
+        II->getOperand(2) != PtrAuthBundleOrNone->Inputs[1])
+      return nullptr;
+    NewCallee = II->getOperand(0);
+    break;
+  }
+  }
+
+  if (!NewCallee)
+    return nullptr;
+
+  NewCallee = Builder.CreateBitOrPointerCast(NewCallee, Callee->getType());
+  CallBase *NewCall = nullptr;
+  if (auto *CI = dyn_cast<CallInst>(&Call)) {
+    NewCall = CallInst::Create(CI, NewBundles);
+  } else {
+    auto *IKI = cast<InvokeInst>(&Call);
+    NewCall = InvokeInst::Create(IKI, NewBundles);
+  }
+  NewCall->setCalledOperand(NewCallee);
+  return NewCall;
+}
+
 bool InstCombinerImpl::annotateAnyAllocSite(CallBase &Call,
                                             const TargetLibraryInfo *TLI) {
   // Note: We only handle cases which can't be driven from generic attributes
@@ -3812,6 +3884,10 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
   if (IntrinsicInst *II = findInitTrampoline(Callee))
     return transformCallThroughTrampoline(Call, *II);
 
+  // Combine calls involving pointer authentication intrinsics.
+  if (Instruction *NewCall = foldPtrAuthIntrinsicCallee(Call))
+    return NewCall;
+
   if (isa<InlineAsm>(Callee) && !Call.doesNotThrow()) {
     InlineAsm *IA = cast<InlineAsm>(Callee);
     if (!IA->canThrow()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 984f02bcccad7..f290f446b424e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -282,6 +282,14 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *transformCallThroughTrampoline(CallBase &Call,
                                               IntrinsicInst &Tramp);
 
+  /// Try to optimize a call to the result of a ptrauth intrinsic, potentially
+  /// into the ptrauth call bundle:
+  /// - call(ptrauth.resign(p)), ["ptrauth"()] ->  call p, ["ptrauth"()]
+  /// - call(ptrauth.sign(p)),   ["ptrauth"()] ->  call p
+  /// as long as the key/discriminator are the same in sign and auth-bundle,
+  /// and we don't change the key in the bundle (to a potentially-invalid key.)
+  Instruction *foldPtrAuthIntrinsicCallee(CallBase &Call);
+
   // Return (a, b) if (LHS, RHS) is known to be (a, b) or (b, a).
   // Otherwise, return std::nullopt
   // Currently it matches:
diff --git a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
new file mode 100644
index 0000000000000..900fd43f01602
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
@@ -0,0 +1,76 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i32 @test_ptrauth_call_resign(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_resign(
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]() [ "ptrauth"(i32 1, i64 1234) ]
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.resign(i64 %v0, i32 1, i64 1234, i32 1, i64 5678)
+  %v2 = inttoptr i64 %v1 to i32()*
+  %v3 = call i32 %v2() [ "ptrauth"(i32 1, i64 5678) ]
+  ret i32 %v3
+}
+
+define i32 @test_ptrauth_call_resign_blend(ptr %pp) {
+; CHECK-LABEL: @test_ptrauth_call_resign_blend(
+; CHECK-NEXT:    [[V01:%.*]] = load ptr, ptr [[PP:%.*]], align 8
+; CHECK-NEXT:    [[V6:%.*]] = call i32 [[V01]]() [ "ptrauth"(i32 1, i64 1234) ]
+; CHECK-NEXT:    ret i32 [[V6]]
+;
+  %v0 = load ptr, ptr %pp, align 8
+  %v1 = ptrtoint ptr %pp to i64
+  %v2 = ptrtoint ptr %v0 to i64
+  %v3 = call i64 @llvm.ptrauth.blend(i64 %v1, i64 5678)
+  %v4 = call i64 @llvm.ptrauth.resign(i64 %v2, i32 1, i64 1234, i32 1, i64 %v3)
+  %v5 = inttoptr i64 %v4 to i32()*
+  %v6 = call i32 %v5() [ "ptrauth"(i32 1, i64 %v3) ]
+  ret i32 %v6
+}
+
+define i32 @test_ptrauth_call_resign_blend_2(ptr %pp) {
+; CHECK-LABEL: @test_ptrauth_call_resign_blend_2(
+; CHECK-NEXT:    [[V01:%.*]] = load ptr, ptr [[PP:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = ptrtoint ptr [[PP]] to i64
+; CHECK-NEXT:    [[V3:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[V1]], i64 5678)
+; CHECK-NEXT:    [[V6:%.*]] = call i32 [[V01]]() [ "ptrauth"(i32 0, i64 [[V3]]) ]
+; CHECK-NEXT:    ret i32 [[V6]]
+;
+  %v0 = load ptr, ptr %pp, align 8
+  %v1 = ptrtoint ptr %pp to i64
+  %v2 = ptrtoint ptr %v0 to i64
+  %v3 = call i64 @llvm.ptrauth.blend(i64 %v1, i64 5678)
+  %v4 = call i64 @llvm.ptrauth.resign(i64 %v2, i32 0, i64 %v3, i32 0, i64 1234)
+  %v5 = inttoptr i64 %v4 to i32()*
+  %v6 = call i32 %v5() [ "ptrauth"(i32 0, i64 1234) ]
+  ret i32 %v6
+}
+
+define i32 @test_ptrauth_call_sign(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_sign(
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]()
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v2 = inttoptr i64 %v1 to i32()*
+  %v3 = call i32 %v2() [ "ptrauth"(i32 2, i64 5678) ]
+  ret i32 %v3
+}
+
+define i32 @test_ptrauth_call_sign_otherbundle(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_sign_otherbundle(
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]() [ "somebundle"(ptr null), "otherbundle"(i64 0) ]
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v2 = inttoptr i64 %v1 to i32()*
+  %v3 = call i32 %v2() [ "somebundle"(ptr null), "ptrauth"(i32 2, i64 5678), "otherbundle"(i64 0) ]
+  ret i32 %v3
+}
+
+declare i64 @llvm.ptrauth.sign(i64, i32, i64)
+declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)
+declare i64 @llvm.ptrauth.blend(i64, i64)

>From 5ea8d7462c007f6d3cad010be3d1fd26e4b8748b Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Thu, 13 Jun 2024 13:28:43 -0700
Subject: [PATCH 2/4] Replace typed pointers in casts with ptr.

---
 .../Transforms/InstCombine/ptrauth-intrinsics-call.ll  | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
index 900fd43f01602..5767839363f01 100644
--- a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
+++ b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
@@ -8,7 +8,7 @@ define i32 @test_ptrauth_call_resign(ptr %p) {
 ;
   %v0 = ptrtoint ptr %p to i64
   %v1 = call i64 @llvm.ptrauth.resign(i64 %v0, i32 1, i64 1234, i32 1, i64 5678)
-  %v2 = inttoptr i64 %v1 to i32()*
+  %v2 = inttoptr i64 %v1 to ptr
   %v3 = call i32 %v2() [ "ptrauth"(i32 1, i64 5678) ]
   ret i32 %v3
 }
@@ -24,7 +24,7 @@ define i32 @test_ptrauth_call_resign_blend(ptr %pp) {
   %v2 = ptrtoint ptr %v0 to i64
   %v3 = call i64 @llvm.ptrauth.blend(i64 %v1, i64 5678)
   %v4 = call i64 @llvm.ptrauth.resign(i64 %v2, i32 1, i64 1234, i32 1, i64 %v3)
-  %v5 = inttoptr i64 %v4 to i32()*
+  %v5 = inttoptr i64 %v4 to ptr
   %v6 = call i32 %v5() [ "ptrauth"(i32 1, i64 %v3) ]
   ret i32 %v6
 }
@@ -42,7 +42,7 @@ define i32 @test_ptrauth_call_resign_blend_2(ptr %pp) {
   %v2 = ptrtoint ptr %v0 to i64
   %v3 = call i64 @llvm.ptrauth.blend(i64 %v1, i64 5678)
   %v4 = call i64 @llvm.ptrauth.resign(i64 %v2, i32 0, i64 %v3, i32 0, i64 1234)
-  %v5 = inttoptr i64 %v4 to i32()*
+  %v5 = inttoptr i64 %v4 to ptr
   %v6 = call i32 %v5() [ "ptrauth"(i32 0, i64 1234) ]
   ret i32 %v6
 }
@@ -54,7 +54,7 @@ define i32 @test_ptrauth_call_sign(ptr %p) {
 ;
   %v0 = ptrtoint ptr %p to i64
   %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
-  %v2 = inttoptr i64 %v1 to i32()*
+  %v2 = inttoptr i64 %v1 to ptr
   %v3 = call i32 %v2() [ "ptrauth"(i32 2, i64 5678) ]
   ret i32 %v3
 }
@@ -66,7 +66,7 @@ define i32 @test_ptrauth_call_sign_otherbundle(ptr %p) {
 ;
   %v0 = ptrtoint ptr %p to i64
   %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
-  %v2 = inttoptr i64 %v1 to i32()*
+  %v2 = inttoptr i64 %v1 to ptr
   %v3 = call i32 %v2() [ "somebundle"(ptr null), "ptrauth"(i32 2, i64 5678), "otherbundle"(i64 0) ]
   ret i32 %v3
 }

>From fa689d575605cdba0d2cc760b8e97c97cfa34487 Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Tue, 15 Jul 2025 10:46:28 -0700
Subject: [PATCH 3/4] Simplify a bit and address review feedback.

---
 .../InstCombine/InstCombineCalls.cpp          | 45 ++++++++++---------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8b970626dcddf..59d0327e1ae51 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -4051,15 +4051,19 @@ static IntrinsicInst *findInitTrampoline(Value *Callee) {
 }
 
 Instruction *InstCombinerImpl::foldPtrAuthIntrinsicCallee(CallBase &Call) {
-  Value *Callee = Call.getCalledOperand();
-  auto *IPC = dyn_cast<IntToPtrInst>(Callee);
+  const Value *Callee = Call.getCalledOperand();
+  const auto *IPC = dyn_cast<IntToPtrInst>(Callee);
   if (!IPC || !IPC->isNoopCast(DL))
     return nullptr;
 
-  IntrinsicInst *II = dyn_cast<IntrinsicInst>(IPC->getOperand(0));
+  const auto *II = dyn_cast<IntrinsicInst>(IPC->getOperand(0));
   if (!II)
     return nullptr;
 
+  Intrinsic::ID IIID = II->getIntrinsicID();
+  if (IIID != Intrinsic::ptrauth_resign && IIID != Intrinsic::ptrauth_sign)
+    return nullptr;
+
   // Isolate the ptrauth bundle from the others.
   std::optional<OperandBundleUse> PtrAuthBundleOrNone;
   SmallVector<OperandBundleDef, 2> NewBundles;
@@ -4071,20 +4075,23 @@ Instruction *InstCombinerImpl::foldPtrAuthIntrinsicCallee(CallBase &Call) {
       NewBundles.emplace_back(Bundle);
   }
 
-  Value *NewCallee = nullptr;
-  switch (II->getIntrinsicID()) {
-  default:
+  if (!PtrAuthBundleOrNone)
     return nullptr;
 
+  Value *NewCallee = nullptr;
+  switch (IIID) {
   // call(ptrauth.resign(p)), ["ptrauth"()] ->  call p, ["ptrauth"()]
   // assuming the call bundle and the sign operands match.
   case Intrinsic::ptrauth_resign: {
-    if (!PtrAuthBundleOrNone ||
-        II->getOperand(3) != PtrAuthBundleOrNone->Inputs[0] ||
-        II->getOperand(4) != PtrAuthBundleOrNone->Inputs[1])
+    // Resign result key should match bundle.
+    if (II->getOperand(3) != PtrAuthBundleOrNone->Inputs[0])
+      return nullptr;
+    // Resign result discriminator should match bundle.
+    if (II->getOperand(4) != PtrAuthBundleOrNone->Inputs[1])
       return nullptr;
 
-    // Don't change the key used in the call; we don't know what's valid.
+    // Resign input (auth) key should also match: we can't change the key on
+    // the new call we're generating, because we don't know what keys are valid.
     if (II->getOperand(1) != PtrAuthBundleOrNone->Inputs[0])
       return nullptr;
 
@@ -4098,26 +4105,24 @@ Instruction *InstCombinerImpl::foldPtrAuthIntrinsicCallee(CallBase &Call) {
   // assuming the call bundle and the sign operands match.
   // Non-ptrauth indirect calls are undesirable, but so is ptrauth.sign.
   case Intrinsic::ptrauth_sign: {
-    if (!PtrAuthBundleOrNone ||
-        II->getOperand(1) != PtrAuthBundleOrNone->Inputs[0] ||
-        II->getOperand(2) != PtrAuthBundleOrNone->Inputs[1])
+    // Sign key should match bundle.
+    if (II->getOperand(1) != PtrAuthBundleOrNone->Inputs[0])
+      return nullptr;
+    // Sign discriminator should match bundle.
+    if (II->getOperand(2) != PtrAuthBundleOrNone->Inputs[1])
       return nullptr;
     NewCallee = II->getOperand(0);
     break;
   }
+  default:
+    llvm_unreachable("unexpected intrinsic ID");
   }
 
   if (!NewCallee)
     return nullptr;
 
   NewCallee = Builder.CreateBitOrPointerCast(NewCallee, Callee->getType());
-  CallBase *NewCall = nullptr;
-  if (auto *CI = dyn_cast<CallInst>(&Call)) {
-    NewCall = CallInst::Create(CI, NewBundles);
-  } else {
-    auto *IKI = cast<InvokeInst>(&Call);
-    NewCall = InvokeInst::Create(IKI, NewBundles);
-  }
+  CallBase *NewCall = CallBase::Create(&Call, NewBundles);
   NewCall->setCalledOperand(NewCallee);
   return NewCall;
 }

>From a27020bffc6eb5c46b996c0ffba07db4eb6bfebe Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Tue, 15 Jul 2025 10:57:48 -0700
Subject: [PATCH 4/4] Add more tests.

---
 .../InstCombine/ptrauth-intrinsics-call.ll    | 86 ++++++++++++++++---
 1 file changed, 76 insertions(+), 10 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
index 5767839363f01..5e597c9155f40 100644
--- a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
+++ b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics-call.ll
@@ -1,6 +1,30 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
+define i32 @test_ptrauth_call_sign(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_sign(
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]()
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v2 = inttoptr i64 %v1 to ptr
+  %v3 = call i32 %v2() [ "ptrauth"(i32 2, i64 5678) ]
+  ret i32 %v3
+}
+
+define i32 @test_ptrauth_call_sign_otherbundle(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_sign_otherbundle(
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]() [ "somebundle"(ptr null), "otherbundle"(i64 0) ]
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v2 = inttoptr i64 %v1 to ptr
+  %v3 = call i32 %v2() [ "somebundle"(ptr null), "ptrauth"(i32 2, i64 5678), "otherbundle"(i64 0) ]
+  ret i32 %v3
+}
+
 define i32 @test_ptrauth_call_resign(ptr %p) {
 ; CHECK-LABEL: @test_ptrauth_call_resign(
 ; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]() [ "ptrauth"(i32 1, i64 1234) ]
@@ -47,27 +71,69 @@ define i32 @test_ptrauth_call_resign_blend_2(ptr %pp) {
   ret i32 %v6
 }
 
-define i32 @test_ptrauth_call_sign(ptr %p) {
-; CHECK-LABEL: @test_ptrauth_call_sign(
-; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]()
+define i32 @test_ptrauth_call_resign_mismatch_key(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_resign_mismatch_key(
+; CHECK-NEXT:    [[V0:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[V1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[V0]], i32 1, i64 1234, i32 0, i64 5678)
+; CHECK-NEXT:    [[V2:%.*]] = inttoptr i64 [[V1]] to ptr
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[V2]]() [ "ptrauth"(i32 1, i64 5678) ]
 ; CHECK-NEXT:    ret i32 [[V3]]
 ;
   %v0 = ptrtoint ptr %p to i64
-  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v1 = call i64 @llvm.ptrauth.resign(i64 %v0, i32 1, i64 1234, i32 0, i64 5678)
   %v2 = inttoptr i64 %v1 to ptr
-  %v3 = call i32 %v2() [ "ptrauth"(i32 2, i64 5678) ]
+  %v3 = call i32 %v2() [ "ptrauth"(i32 1, i64 5678) ]
   ret i32 %v3
 }
 
-define i32 @test_ptrauth_call_sign_otherbundle(ptr %p) {
-; CHECK-LABEL: @test_ptrauth_call_sign_otherbundle(
-; CHECK-NEXT:    [[V3:%.*]] = call i32 [[P:%.*]]() [ "somebundle"(ptr null), "otherbundle"(i64 0) ]
+define i32 @test_ptrauth_call_resign_mismatch_disc(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_resign_mismatch_disc(
+; CHECK-NEXT:    [[V0:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[V1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[V0]], i32 1, i64 1234, i32 0, i64 9900)
+; CHECK-NEXT:    [[V2:%.*]] = inttoptr i64 [[V1]] to ptr
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[V2]]() [ "ptrauth"(i32 1, i64 5678) ]
 ; CHECK-NEXT:    ret i32 [[V3]]
 ;
   %v0 = ptrtoint ptr %p to i64
-  %v1 = call i64 @llvm.ptrauth.sign(i64 %v0, i32 2, i64 5678)
+  %v1 = call i64 @llvm.ptrauth.resign(i64 %v0, i32 1, i64 1234, i32 0, i64 9900)
   %v2 = inttoptr i64 %v1 to ptr
-  %v3 = call i32 %v2() [ "somebundle"(ptr null), "ptrauth"(i32 2, i64 5678), "otherbundle"(i64 0) ]
+  %v3 = call i32 %v2() [ "ptrauth"(i32 1, i64 5678) ]
+  ret i32 %v3
+}
+
+define i32 @test_ptrauth_call_resign_mismatch_blend(ptr %pp) {
+; CHECK-LABEL: @test_ptrauth_call_resign_mismatch_blend(
+; CHECK-NEXT:    [[V0:%.*]] = load ptr, ptr [[PP:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = ptrtoint ptr [[PP]] to i64
+; CHECK-NEXT:    [[V2:%.*]] = ptrtoint ptr [[V0]] to i64
+; CHECK-NEXT:    [[V6:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[V1]], i64 5678)
+; CHECK-NEXT:    [[V4:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[V2]], i32 1, i64 1234, i32 1, i64 [[V6]])
+; CHECK-NEXT:    [[V5:%.*]] = inttoptr i64 [[V4]] to ptr
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[V5]]() [ "ptrauth"(i32 1, i64 [[V1]]) ]
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = load ptr, ptr %pp, align 8
+  %v1 = ptrtoint ptr %pp to i64
+  %v2 = ptrtoint ptr %v0 to i64
+  %v3 = call i64 @llvm.ptrauth.blend(i64 %v1, i64 5678)
+  %v4 = call i64 @llvm.ptrauth.resign(i64 %v2, i32 1, i64 1234, i32 1, i64 %v3)
+  %v5 = inttoptr i64 %v4 to ptr
+  %v6 = call i32 %v5() [ "ptrauth"(i32 1, i64 %v1) ]
+  ret i32 %v6
+}
+
+define i32 @test_ptrauth_call_resign_changing_call_key(ptr %p) {
+; CHECK-LABEL: @test_ptrauth_call_resign_changing_call_key(
+; CHECK-NEXT:    [[V0:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[V1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[V0]], i32 2, i64 1234, i32 1, i64 5678)
+; CHECK-NEXT:    [[V2:%.*]] = inttoptr i64 [[V1]] to ptr
+; CHECK-NEXT:    [[V3:%.*]] = call i32 [[V2]]() [ "ptrauth"(i32 1, i64 5678) ]
+; CHECK-NEXT:    ret i32 [[V3]]
+;
+  %v0 = ptrtoint ptr %p to i64
+  %v1 = call i64 @llvm.ptrauth.resign(i64 %v0, i32 2, i64 1234, i32 1, i64 5678)
+  %v2 = inttoptr i64 %v1 to ptr
+  %v3 = call i32 %v2() [ "ptrauth"(i32 1, i64 5678) ]
   ret i32 %v3
 }
 



More information about the llvm-commits mailing list