Skip to content

Commit 02a5496

Browse files
committed
[InstCombine] Combine ptrauth constants into ptrauth intrinsics.
When we encounter two consecutive ptrauth intrinsics, we can already combine the inner matching sign + auth pair, e.g.: resign(sign(p,ks,ds),ks,ds,kr,dr) -> sign(p,kr,dr) We can generalize that to ptrauth constants, which are effectively constant equivalents to ptrauth.sign, i.e.: resign(ptrauth(p,ks,ds),ks,ds,kr,dr) -> ptrauth(p,kr,dr) auth(ptrauth(p,k,d),k,d) -> p
1 parent 86070a8 commit 02a5496

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2625,13 +2625,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
26252625
// (sign|resign) + (auth|resign) can be folded by omitting the middle
26262626
// sign+auth component if the key and discriminator match.
26272627
bool NeedSign = II->getIntrinsicID() == Intrinsic::ptrauth_resign;
2628+
Value *Ptr = II->getArgOperand(0);
26282629
Value *Key = II->getArgOperand(1);
26292630
Value *Disc = II->getArgOperand(2);
26302631

26312632
// AuthKey will be the key we need to end up authenticating against in
26322633
// whatever we replace this sequence with.
26332634
Value *AuthKey = nullptr, *AuthDisc = nullptr, *BasePtr;
2634-
if (auto CI = dyn_cast<CallBase>(II->getArgOperand(0))) {
2635+
if (auto *CI = dyn_cast<CallBase>(Ptr)) {
26352636
BasePtr = CI->getArgOperand(0);
26362637
if (CI->getIntrinsicID() == Intrinsic::ptrauth_sign) {
26372638
if (CI->getArgOperand(1) != Key || CI->getArgOperand(2) != Disc)
@@ -2643,6 +2644,28 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
26432644
AuthDisc = CI->getArgOperand(2);
26442645
} else
26452646
break;
2647+
} else if (auto *PtrToInt = dyn_cast<PtrToIntOperator>(Ptr)) {
2648+
// ptrauth constants are equivalent to a call to @llvm.ptrauth.sign for
2649+
// our purposes, so check for that too.
2650+
auto *CPA = dyn_cast<ConstantPtrAuth>(PtrToInt->getOperand(0));
2651+
if (!CPA || !CPA->isKnownCompatibleWith(Key, Disc, DL))
2652+
break;
2653+
2654+
// resign(ptrauth(p,ks,ds),ks,ds,kr,dr) -> ptrauth(p,kr,dr)
2655+
if (NeedSign && isa<ConstantInt>(II->getArgOperand(4))) {
2656+
auto *SignKey = cast<ConstantInt>(II->getArgOperand(3));
2657+
auto *SignDisc = cast<ConstantInt>(II->getArgOperand(4));
2658+
auto *SignAddrDisc = ConstantPointerNull::get(Builder.getPtrTy());
2659+
auto *NewCPA = ConstantPtrAuth::get(CPA->getPointer(), SignKey,
2660+
SignDisc, SignAddrDisc);
2661+
replaceInstUsesWith(
2662+
*II, ConstantExpr::getPointerCast(NewCPA, II->getType()));
2663+
eraseInstFromFunction(*II);
2664+
return nullptr;
2665+
}
2666+
2667+
// auth(ptrauth(p,k,d),k,d) -> p
2668+
BasePtr = Builder.CreatePtrToInt(CPA->getPointer(), II->getType());
26462669
} else
26472670
break;
26482671

llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@ define i64 @test_ptrauth_nop(ptr %p) {
1212
ret i64 %authed
1313
}
1414

15+
declare void @foo()
16+
17+
define i64 @test_ptrauth_nop_constant() {
18+
; CHECK-LABEL: @test_ptrauth_nop_constant(
19+
; CHECK-NEXT: ret i64 ptrtoint (ptr @foo to i64)
20+
;
21+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234) to i64), i32 1, i64 1234)
22+
ret i64 %authed
23+
}
24+
25+
define i64 @test_ptrauth_nop_constant_addrdisc() {
26+
; CHECK-LABEL: @test_ptrauth_nop_constant_addrdisc(
27+
; CHECK-NEXT: ret i64 ptrtoint (ptr @foo to i64)
28+
;
29+
%addr = ptrtoint void()* @foo to i64
30+
%blended = call i64 @llvm.ptrauth.blend(i64 %addr, i64 1234)
31+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234, ptr @foo) to i64), i32 1, i64 %blended)
32+
ret i64 %authed
33+
}
34+
1535
define i64 @test_ptrauth_nop_mismatch(ptr %p) {
1636
; CHECK-LABEL: @test_ptrauth_nop_mismatch(
1737
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[P:%.*]] to i64
@@ -87,6 +107,59 @@ define i64 @test_ptrauth_resign_auth_mismatch(ptr %p) {
87107
ret i64 %authed
88108
}
89109

110+
define i64 @test_ptrauth_nop_constant_mismatch() {
111+
; CHECK-LABEL: @test_ptrauth_nop_constant_mismatch(
112+
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 ptrtoint (ptr ptrauth (ptr @foo, i32 1, i64 1234) to i64), i32 1, i64 12)
113+
; CHECK-NEXT: ret i64 [[AUTHED]]
114+
;
115+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234) to i64), i32 1, i64 12)
116+
ret i64 %authed
117+
}
118+
119+
define i64 @test_ptrauth_nop_constant_mismatch_key() {
120+
; CHECK-LABEL: @test_ptrauth_nop_constant_mismatch_key(
121+
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 ptrtoint (ptr ptrauth (ptr @foo, i32 1, i64 1234) to i64), i32 0, i64 1234)
122+
; CHECK-NEXT: ret i64 [[AUTHED]]
123+
;
124+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234) to i64), i32 0, i64 1234)
125+
ret i64 %authed
126+
}
127+
128+
define i64 @test_ptrauth_nop_constant_addrdisc_mismatch() {
129+
; CHECK-LABEL: @test_ptrauth_nop_constant_addrdisc_mismatch(
130+
; CHECK-NEXT: [[BLENDED:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @foo to i64), i64 12)
131+
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 ptrtoint (ptr ptrauth (ptr @foo, i32 1, i64 1234, ptr @foo) to i64), i32 1, i64 [[BLENDED]])
132+
; CHECK-NEXT: ret i64 [[AUTHED]]
133+
;
134+
%addr = ptrtoint ptr @foo to i64
135+
%blended = call i64 @llvm.ptrauth.blend(i64 %addr, i64 12)
136+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234, ptr @foo) to i64), i32 1, i64 %blended)
137+
ret i64 %authed
138+
}
139+
140+
define i64 @test_ptrauth_nop_constant_addrdisc_mismatch2() {
141+
; CHECK-LABEL: @test_ptrauth_nop_constant_addrdisc_mismatch2(
142+
; CHECK-NEXT: [[BLENDED:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @test_ptrauth_nop to i64), i64 1234)
143+
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 ptrtoint (ptr ptrauth (ptr @foo, i32 1, i64 1234, ptr @foo) to i64), i32 1, i64 [[BLENDED]])
144+
; CHECK-NEXT: ret i64 [[AUTHED]]
145+
;
146+
%addr = ptrtoint ptr @test_ptrauth_nop to i64
147+
%blended = call i64 @llvm.ptrauth.blend(i64 %addr, i64 1234)
148+
%authed = call i64 @llvm.ptrauth.auth(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234, ptr @foo) to i64), i32 1, i64 %blended)
149+
ret i64 %authed
150+
}
151+
152+
define i64 @test_ptrauth_resign_ptrauth_constant(ptr %p) {
153+
; CHECK-LABEL: @test_ptrauth_resign_ptrauth_constant(
154+
; CHECK-NEXT: ret i64 ptrtoint (ptr ptrauth (ptr @foo, i32 0, i64 42) to i64)
155+
;
156+
157+
%tmp0 = ptrtoint ptr %p to i64
158+
%authed = call i64 @llvm.ptrauth.resign(i64 ptrtoint(ptr ptrauth(ptr @foo, i32 1, i64 1234) to i64), i32 1, i64 1234, i32 0, i64 42)
159+
ret i64 %authed
160+
}
161+
90162
declare i64 @llvm.ptrauth.auth(i64, i32, i64)
91163
declare i64 @llvm.ptrauth.sign(i64, i32, i64)
92164
declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)
165+
declare i64 @llvm.ptrauth.blend(i64, i64)

0 commit comments

Comments
 (0)