[llvm] [PtrAuth] Add ConstantPtrAuth comparator to FunctionComparator.cpp (PR #159480)
Oskar Wirga via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 18 14:12:15 PDT 2025
https://github.com/oskarwirga updated https://github.com/llvm/llvm-project/pull/159480
>From 10f5e779499abb474607e855631a74dacd386f6f Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar.wirga at gmail.com>
Date: Thu, 11 Sep 2025 19:16:40 -0700
Subject: [PATCH] [PtrAuth] Add ConstantPtrAuth comparator to
FunctionComparator.cpp
When building rustc std for arm64e, the optimizations result in devirtualization of indirect calls.
This can happen during function merging so I modified FunctionComparator.cpp as the ConstantPtrAuth value would go unchecked in the switch statement.
---
.../Transforms/Utils/FunctionComparator.cpp | 17 +++
.../MergeFunc/ptrauth-const-compare.ll | 101 ++++++++++++++++++
2 files changed, 118 insertions(+)
create mode 100644 llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll
diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
index 6d4026e8209de..8aba7886c9051 100644
--- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
@@ -354,6 +354,23 @@ int FunctionComparator::cmpConstants(const Constant *L,
if (!L->isNullValue() && R->isNullValue())
return -1;
+ // Handle authenticated pointer constants produced by ConstantPtrAuth::get.
+ if (auto *PA1 = dyn_cast<ConstantPtrAuth>(L)) {
+ auto *PA2 = dyn_cast<ConstantPtrAuth>(R);
+ if (!PA2)
+ return cmpNumbers(L->getValueID(), R->getValueID());
+
+ if (int Res = cmpConstants(PA1->getPointer(), PA2->getPointer()))
+ return Res;
+ if (int Res = cmpConstants(PA1->getKey(), PA2->getKey()))
+ return Res;
+ if (int Res =
+ cmpConstants(PA1->getDiscriminator(), PA2->getDiscriminator()))
+ return Res;
+ return cmpConstants(PA1->getAddrDiscriminator(),
+ PA2->getAddrDiscriminator());
+ }
+
auto GlobalValueL = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(L));
auto GlobalValueR = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(R));
if (GlobalValueL && GlobalValueR) {
diff --git a/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll b/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll
new file mode 100644
index 0000000000000..b3877f21213f9
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/ptrauth-const-compare.ll
@@ -0,0 +1,101 @@
+; RUN: opt -passes=mergefunc -S %s | FileCheck %s
+; Ensure MergeFunc handles ConstantPtrAuth correctly and does not
+; merge when any ptrauth operand differs (ptr, key, int disc, addr disc).
+
+target triple = "arm64e-apple-ios14.0.0"
+
+declare void @baz()
+ at ADDR = external global i8
+
+declare void @sink0()
+declare void @sink1()
+declare void @sink2()
+declare void @sink3()
+
+; different base pointer (null vs @baz)
+
+define void @f_ptr_null() {
+; CHECK-LABEL: define void @f_ptr_null()
+; CHECK: call void @sink0()
+; CHECK: call void ptrauth (ptr null, i32 0)(
+entry:
+ call void @sink0()
+ call void ptrauth (ptr null, i32 0)(ptr null)
+ ret void
+}
+
+define void @g_ptr_baz() {
+; CHECK-LABEL: define void @g_ptr_baz()
+; CHECK: call void @sink0()
+; CHECK: call void ptrauth (ptr @baz, i32 0)(
+entry:
+ call void @sink0()
+ call void ptrauth (ptr @baz, i32 0)(ptr null)
+ ret void
+}
+
+; different key (i32 0 vs i32 1)
+
+define void @f_key0() {
+; CHECK-LABEL: define void @f_key0()
+; CHECK: call void @sink1()
+; CHECK: call void ptrauth (ptr @baz, i32 0)(
+entry:
+ call void @sink1()
+ call void ptrauth (ptr @baz, i32 0)(ptr null)
+ ret void
+}
+
+define void @g_key1() {
+; CHECK-LABEL: define void @g_key1()
+; CHECK: call void @sink1()
+; CHECK: call void ptrauth (ptr @baz, i32 1)(
+entry:
+ call void @sink1()
+ call void ptrauth (ptr @baz, i32 1)(ptr null)
+ ret void
+}
+
+; different integer disc (i64 0 vs i64 7)
+
+define void @f_disc0() {
+; CHECK-LABEL: define void @f_disc0()
+; CHECK: call void @sink2()
+; CHECK: call void ptrauth (ptr @baz, i32 0)(
+entry:
+ call void @sink2()
+ call void ptrauth (ptr @baz, i32 0)(ptr null)
+ ret void
+}
+
+define void @g_disc7() {
+; CHECK-LABEL: define void @g_disc7()
+; CHECK: call void @sink2()
+; CHECK: call void ptrauth (ptr @baz, i32 0, i64 7)(
+entry:
+ call void @sink2()
+ call void ptrauth (ptr @baz, i32 0, i64 7)(ptr null)
+ ret void
+}
+
+; different addr disc (ptr null vs @ADDR)
+
+define void @f_addr_null() {
+; CHECK-LABEL: define void @f_addr_null()
+; CHECK: call void @sink3()
+; CHECK: call void ptrauth (ptr @baz, i32 0)(
+entry:
+ call void @sink3()
+ call void ptrauth (ptr @baz, i32 0)(ptr null)
+ ret void
+}
+
+define void @g_addr_ADDR() {
+; CHECK-LABEL: define void @g_addr_ADDR()
+; CHECK: call void @sink3()
+; CHECK: call void ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR)(
+entry:
+ call void @sink3()
+ call void ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR)(ptr null)
+ ret void
+}
More information about the llvm-commits
mailing list