diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 9ae3f4e866b4..51f7843543a3 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -482,6 +482,52 @@ bool PreISelIntrinsicLowering::expandMemIntrinsicUses( return Changed; } +static GlobalValue *getDeactivationSymbol(CallInst *Call) { + if (auto Bundle = Call->getOperandBundle(LLVMContext::OB_deactivation_symbol)) + return cast(Bundle->Inputs[0]); + return nullptr; +} + +static bool expandPtrauthForEmuPAC(Function &Intr) { + Module &M = *Intr.getParent(); + if (Triple(M.getTargetTriple()).isArm64e()) + return false; + + Type *Int64Ty = Type::getInt64Ty(M.getContext()); + + assert(Intr.getIntrinsicID() == Intrinsic::ptrauth_sign || + Intr.getIntrinsicID() == Intrinsic::ptrauth_auth); + auto *EmuFnTy = FunctionType::get(Int64Ty, {Int64Ty, Int64Ty}, false); + FunctionCallee EmuIntr = M.getOrInsertFunction( + Intr.getIntrinsicID() == Intrinsic::ptrauth_auth ? "__emupac_autda" + : "__emupac_pacda", + EmuFnTy); + + for (User *U : llvm::make_early_inc_range(Intr.users())) { + auto *Call = cast(U); + // We only support the DA key for now. + if (auto *Key = dyn_cast(Call->getArgOperand(1)); + !Key || Key->getZExtValue() != /*AArch64PACKey::DA*/ 2) + continue; + + Function *F = Call->getParent()->getParent(); + Attribute FSAttr = F->getFnAttribute("target-features"); + if (FSAttr.isValid() && FSAttr.getValueAsString().contains("+pauth")) + continue; + + std::vector DSBundle; + if (auto *DS = getDeactivationSymbol(Call)) + DSBundle.push_back(OperandBundleDef("deactivation-symbol", DS)); + + IRBuilder<> B(Call); + auto *EmuCall = B.CreateCall( + EmuIntr, {Call->getArgOperand(0), Call->getArgOperand(2)}, DSBundle); + Call->replaceAllUsesWith(EmuCall); + Call->eraseFromParent(); + } + return true; +} + static bool expandProtectedFieldPtr(Function &Intr) { Module &M = *Intr.getParent(); @@ -491,89 +537,19 @@ static bool expandProtectedFieldPtr(Function &Intr) { Type *Int64Ty = Type::getInt64Ty(M.getContext()); PointerType *PtrTy = PointerType::get(M.getContext(), 0); - Function *SignIntr = - Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_sign, {}); - Function *AuthIntr = - Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_auth, {}); - - auto *EmuFnTy = FunctionType::get(Int64Ty, {Int64Ty, Int64Ty}, false); - - auto CreateSign = [&](IRBuilder<> &B, Value *Val, Value *Disc, - OperandBundleDef DSBundle) { - Function *F = B.GetInsertBlock()->getParent(); - Attribute FSAttr = F->getFnAttribute("target-features"); - if (FSAttr.isValid() && FSAttr.getValueAsString().contains("+pauth")) - return B.CreateCall( - SignIntr, {Val, B.getInt32(/*AArch64PACKey::DA*/ 2), Disc}, DSBundle); - FunctionCallee EmuSignIntr = - M.getOrInsertFunction("__emupac_pacda", EmuFnTy); - return B.CreateCall(EmuSignIntr, {Val, Disc}, DSBundle); - }; - - auto CreateAuth = [&](IRBuilder<> &B, Value *Val, Value *Disc, - OperandBundleDef DSBundle) { - Function *F = B.GetInsertBlock()->getParent(); - Attribute FSAttr = F->getFnAttribute("target-features"); - if (FSAttr.isValid() && FSAttr.getValueAsString().contains("+pauth")) - return B.CreateCall( - AuthIntr, {Val, B.getInt32(/*AArch64PACKey::DA*/ 2), Disc}, DSBundle); - FunctionCallee EmuAuthIntr = - M.getOrInsertFunction("__emupac_autda", EmuFnTy); - return B.CreateCall(EmuAuthIntr, {Val, Disc}, DSBundle); - }; - - auto GetDeactivationSymbol = [&](CallInst *Call) -> GlobalValue * { - if (auto Bundle = - Call->getOperandBundle(LLVMContext::OB_deactivation_symbol)) - return cast(Bundle->Inputs[0]); - return nullptr; - }; - for (User *U : llvm::make_early_inc_range(Intr.users())) { auto *Call = cast(U); auto *Pointer = Call->getArgOperand(0); - auto *Disc = Call->getArgOperand(1); bool UseHWEncoding = cast(Call->getArgOperand(2))->getZExtValue(); if (!UseHWEncoding) reportFatalUsageError("software encoding currently unsupported"); - auto *DS = GetDeactivationSymbol(Call); + auto *DS = getDeactivationSymbol(Call); OperandBundleDef DSBundle("deactivation-symbol", DS); for (Use &U : llvm::make_early_inc_range(Call->uses())) { - // Insert code to encode each pointer stored to the pointer returned by - // the intrinsic. - if (auto *SI = dyn_cast(U.getUser())) { - if (U.getOperandNo() == 1 && - isa(SI->getValueOperand()->getType())) { - IRBuilder<> B(SI); - auto *SIValInt = - B.CreatePtrToInt(SI->getValueOperand(), B.getInt64Ty()); - Value *Sign = CreateSign(B, SIValInt, Disc, DSBundle); - SI->setOperand(0, B.CreateIntToPtr(Sign, B.getPtrTy())); - SI->setOperand(1, Pointer); - continue; - } - } - - // Insert code to decode each pointer loaded from the pointer returned by - // the intrinsic. This is the inverse of the encode operation implemented - // above. - if (auto *LI = dyn_cast(U.getUser())) { - if (isa(LI->getType())) { - IRBuilder<> B(LI); - auto *NewLI = cast(LI->clone()); - NewLI->setOperand(0, Pointer); - B.Insert(NewLI); - auto *LIInt = B.CreatePtrToInt(NewLI, B.getInt64Ty()); - Value *Auth = CreateAuth(B, LIInt, Disc, DSBundle); - LI->replaceAllUsesWith(B.CreateIntToPtr(Auth, B.getPtrTy())); - LI->eraseFromParent(); - continue; - } - } // Comparisons against null cannot be used to recover the original // pointer so we replace them with comparisons against the original // pointer. @@ -592,8 +568,12 @@ static bool expandProtectedFieldPtr(Function &Intr) { } } - // We couldn't rewrite away this use of the intrinsic. Replace it with the - // pointer operand, and arrange to define a deactivation symbol. + // If we are here, this means that we couldn't rewrite away this use of + // the intrinsic. Any load or store uses were removed by InstCombine, and + // in general, we can't rewrite away non-load/store uses of + // llvm.protected.field.ptr because doing so could expose the encoded + // pointer value to the program. Replace it with the pointer operand, and + // arrange to define a deactivation symbol. U.set(Pointer); if (DS) DSsToDeactivate.insert(DS); @@ -817,6 +797,10 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const { return lowerUnaryVectorIntrinsicAsLoop(M, CI); }); break; + case Intrinsic::ptrauth_sign: + case Intrinsic::ptrauth_auth: + Changed |= expandPtrauthForEmuPAC(F); + break; case Intrinsic::protected_field_ptr: Changed |= expandProtectedFieldPtr(F); break; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index b414a7ed4fe6..e5ad15dc9594 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3294,25 +3294,25 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { } case Intrinsic::ptrauth_auth: case Intrinsic::ptrauth_resign: { - // We don't support this optimization on intrinsic calls with deactivation - // symbols, which are represented using operand bundles. - if (II->hasOperandBundles()) - break; - // (sign|resign) + (auth|resign) can be folded by omitting the middle // sign+auth component if the key and discriminator match. bool NeedSign = II->getIntrinsicID() == Intrinsic::ptrauth_resign; Value *Ptr = II->getArgOperand(0); Value *Key = II->getArgOperand(1); Value *Disc = II->getArgOperand(2); + Value *DS = nullptr; + if (auto Bundle = II->getOperandBundle(LLVMContext::OB_deactivation_symbol)) + DS = Bundle->Inputs[0]; // AuthKey will be the key we need to end up authenticating against in // whatever we replace this sequence with. Value *AuthKey = nullptr, *AuthDisc = nullptr, *BasePtr; if (const auto *CI = dyn_cast(Ptr)) { - // We don't support this optimization on intrinsic calls with deactivation - // symbols, which are represented using operand bundles. - if (CI->hasOperandBundles()) + Value *OtherDS = nullptr; + if (auto Bundle = + CI->getOperandBundle(LLVMContext::OB_deactivation_symbol)) + OtherDS = Bundle->Inputs[0]; + if (DS != OtherDS) break; BasePtr = CI->getArgOperand(0); @@ -3320,6 +3320,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { if (CI->getArgOperand(1) != Key || CI->getArgOperand(2) != Disc) break; } else if (CI->getIntrinsicID() == Intrinsic::ptrauth_resign) { + // The resign intrinsic does not support deactivation symbols. + assert(!DS); if (CI->getArgOperand(3) != Key || CI->getArgOperand(4) != Disc) break; AuthKey = CI->getArgOperand(1); @@ -3330,7 +3332,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { // ptrauth constants are equivalent to a call to @llvm.ptrauth.sign for // our purposes, so check for that too. const auto *CPA = dyn_cast(PtrToInt->getOperand(0)); - if (!CPA || !CPA->isKnownCompatibleWith(Key, Disc, DL)) + if (!CPA || DS || !CPA->isKnownCompatibleWith(Key, Disc, DL)) break; // resign(ptrauth(p,ks,ds),ks,ds,kr,dr) -> ptrauth(p,kr,dr) @@ -3379,9 +3381,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { CallArgs.push_back(II->getArgOperand(4)); } + std::vector Bundles; + if (DS) + Bundles.push_back(OperandBundleDef("deactivation-symbol", DS)); + Function *NewFn = Intrinsic::getOrInsertDeclaration(II->getModule(), NewIntrin); - return CallInst::Create(NewFn, CallArgs); + return CallInst::Create(NewFn, CallArgs, Bundles); } case Intrinsic::arm_neon_vtbl1: case Intrinsic::arm_neon_vtbl2: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 7d52252a5342..0fe44d615ace 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1184,6 +1184,37 @@ Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) { if (Value *V = simplifyNonNullOperand(Op, /*HasDereferenceable=*/true)) return replaceOperand(LI, 0, V); + // load(llvm.protected.field.ptr(ptr)) -> llvm.ptrauth.auth(load(ptr)) + if (isa(LI.getType())) { + if (auto *II = dyn_cast(Op)) { + if (II->getIntrinsicID() == Intrinsic::protected_field_ptr) { + std::vector DSBundle; + if (auto Bundle = + II->getOperandBundle(LLVMContext::OB_deactivation_symbol)) + DSBundle.push_back(OperandBundleDef( + "deactivation-symbol", cast(Bundle->Inputs[0]))); + + IRBuilderBase::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(&LI); + + auto *NewLI = cast(LI.clone()); + NewLI->setOperand(0, II->getOperand(0)); + Builder.Insert(NewLI); + + Function *AuthIntr = Intrinsic::getOrInsertDeclaration( + F.getParent(), Intrinsic::ptrauth_auth, {}); + auto *LIInt = Builder.CreatePtrToInt(NewLI, Builder.getInt64Ty()); + Value *Auth = Builder.CreateCall( + AuthIntr, + {LIInt, Builder.getInt32(/*AArch64PACKey::DA*/ 2), + II->getOperand(1)}, + DSBundle); + Auth = Builder.CreateIntToPtr(Auth, Builder.getPtrTy()); + return replaceInstUsesWith(LI, Auth); + } + } + } + return nullptr; } @@ -1551,6 +1582,37 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) { if (Value *V = simplifyNonNullOperand(Ptr, /*HasDereferenceable=*/true)) return replaceOperand(SI, 1, V); + // store(ptr1, llvm.protected.field.ptr(ptr2)) -> + // store(llvm.ptrauth.sign(ptr1), ptr2) + if (isa(Val->getType())) { + if (auto *II = dyn_cast(Ptr)) { + if (II->getIntrinsicID() == Intrinsic::protected_field_ptr) { + std::vector DSBundle; + if (auto Bundle = + II->getOperandBundle(LLVMContext::OB_deactivation_symbol)) + DSBundle.push_back(OperandBundleDef( + "deactivation-symbol", cast(Bundle->Inputs[0]))); + + IRBuilderBase::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(&SI); + + Function *SignIntr = Intrinsic::getOrInsertDeclaration( + F.getParent(), Intrinsic::ptrauth_sign, {}); + auto *ValInt = Builder.CreatePtrToInt(Val, Builder.getInt64Ty()); + Value *Sign = Builder.CreateCall( + SignIntr, + {ValInt, Builder.getInt32(/*AArch64PACKey::DA*/ 2), + II->getOperand(1)}, + DSBundle); + Sign = Builder.CreateIntToPtr(Sign, Builder.getPtrTy()); + + replaceOperand(SI, 0, Sign); + replaceOperand(SI, 1, II->getOperand(0)); + return &SI; + } + } + } + return nullptr; } diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 7cab4be16912..49165d80f065 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -2969,12 +2969,6 @@ bool GVNPass::performScalarPRE(Instruction *CurInst) { return false; } - // Protected pointer field loads/stores should be paired with the intrinsic - // to avoid unnecessary address escapes. - if (auto *II = dyn_cast(CurInst)) - if (II->getIntrinsicID() == Intrinsic::protected_field_ptr) - return false; - uint32_t ValNo = VN.lookup(CurInst); // Look for the predecessors for PRE opportunities. We're diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 75af57ffa205..81decd7f9c33 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -3908,12 +3908,6 @@ bool llvm::canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx) { if (Op->isSwiftError()) return false; - // Protected pointer field loads/stores should be paired with the intrinsic - // to avoid unnecessary address escapes. - if (auto *II = dyn_cast(Op)) - if (II->getIntrinsicID() == Intrinsic::protected_field_ptr) - return false; - // Cannot replace alloca argument with phi/select. if (I->isLifetimeStartOrEnd()) return false; diff --git a/llvm/test/Transforms/GVN/PRE/protected-field-ptr.ll b/llvm/test/Transforms/GVN/PRE/protected-field-ptr.ll deleted file mode 100644 index c045242e4eac..000000000000 --- a/llvm/test/Transforms/GVN/PRE/protected-field-ptr.ll +++ /dev/null @@ -1,41 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -passes=gvn -S < %s | FileCheck %s - -; Check that PRE is inhibited for llvm.protected.field.ptr. -declare void @use(ptr) - -define void @test1(i1 %c, ptr %arg) { -; CHECK-LABEL: @test1( -; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[DOTBB2_CRIT_EDGE:%.*]] -; CHECK: bb1: -; CHECK-NEXT: [[CALL:%.*]] = call ptr @llvm.protected.field.ptr.p0(ptr [[ARG:%.*]], i64 1, i1 true) -; CHECK-NEXT: br label [[BB3:%.*]] -; CHECK: bb2: -; CHECK-NEXT: [[CALL2:%.*]] = call ptr @llvm.protected.field.ptr.p0(ptr [[ARG]], i64 1, i1 true) -; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[CALL2]], align 8 -; CHECK-NEXT: call void @use(ptr [[V]]) -; CHECK-NEXT: br label [[BB3]] -; CHECK: bb3: -; CHECK-NEXT: [[CALL3:%.*]] = call ptr @llvm.protected.field.ptr.p0(ptr [[ARG]], i64 1, i1 true) -; CHECK-NEXT: [[V2:%.*]] = load ptr, ptr [[CALL3]], align 8 -; CHECK-NEXT: call void @use(ptr [[V2]]) -; CHECK-NEXT: br label [[DOTBB2_CRIT_EDGE]] -; - br i1 %c, label %bb1, label %bb2 - -bb1: - %call = call ptr @llvm.protected.field.ptr.p0(ptr %arg, i64 1, i1 true) - br label %bb3 - -bb2: - %call2 = call ptr @llvm.protected.field.ptr.p0(ptr %arg, i64 1, i1 true) - %v = load ptr, ptr %call2 - call void @use(ptr %v) - br label %bb3 - -bb3: - %call3 = call ptr @llvm.protected.field.ptr.p0(ptr %arg, i64 1, i1 true) - %v2 = load ptr, ptr %call3 - call void @use(ptr %v2) - br label %bb2 -} diff --git a/llvm/test/Transforms/InstCombine/protected-field-ptr.ll b/llvm/test/Transforms/InstCombine/protected-field-ptr.ll new file mode 100644 index 000000000000..ee9949beffc9 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/protected-field-ptr.ll @@ -0,0 +1,61 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=instcombine -S < %s | FileCheck %s + +@ds1 = external global i8 +@ds2 = external global i8 + +define ptr @load_hw(ptr addrspace(1) %ptrptr) { +; CHECK-LABEL: define ptr @load_hw( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr addrspace(1) [[PTRPTR]], align 8 +; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 1) +; CHECK-NEXT: [[PTR:%.*]] = inttoptr i64 [[TMP3]] to ptr +; CHECK-NEXT: ret ptr [[PTR]] +; + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 1, i1 true) + %ptr = load ptr, ptr addrspace(1) %protptrptr + ret ptr %ptr +} + +define void @store_hw(ptr addrspace(1) %ptrptr, ptr %ptr) { +; CHECK-LABEL: define void @store_hw( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]], ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[TMP1]], i32 2, i64 2) +; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: store ptr [[TMP3]], ptr addrspace(1) [[PTRPTR]], align 8 +; CHECK-NEXT: ret void +; + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 2, i1 true) + store ptr %ptr, ptr addrspace(1) %protptrptr + ret void +} + +define ptr @load_hw_ds(ptr addrspace(1) %ptrptr) { +; CHECK-LABEL: define ptr @load_hw_ds( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr addrspace(1) [[PTRPTR]], align 8 +; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 1) [ "deactivation-symbol"(ptr @ds1) ] +; CHECK-NEXT: [[PTR:%.*]] = inttoptr i64 [[TMP3]] to ptr +; CHECK-NEXT: ret ptr [[PTR]] +; + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 1, i1 true) [ "deactivation-symbol"(ptr @ds1) ] + %ptr = load ptr, ptr addrspace(1) %protptrptr + ret ptr %ptr +} + +define void @store_hw_ds(ptr addrspace(1) %ptrptr, ptr %ptr) { +; CHECK-LABEL: define void @store_hw_ds( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]], ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[TMP1]], i32 2, i64 2) [ "deactivation-symbol"(ptr @ds2) ] +; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: store ptr [[TMP3]], ptr addrspace(1) [[PTRPTR]], align 8 +; CHECK-NEXT: ret void +; + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 2, i1 true) [ "deactivation-symbol"(ptr @ds2) ] + store ptr %ptr, ptr addrspace(1) %protptrptr + ret void +} diff --git a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll index 22c330fe7ae6..784d2c90645b 100644 --- a/llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll @@ -161,6 +161,7 @@ define i64 @test_ptrauth_resign_ptrauth_constant(ptr %p) { } @ds = external global i8 +@ds2 = external global i8 define i64 @test_ptrauth_nop_ds1(ptr %p) { ; CHECK-LABEL: @test_ptrauth_nop_ds1( @@ -188,6 +189,30 @@ define i64 @test_ptrauth_nop_ds2(ptr %p) { ret i64 %authed } +define i64 @test_ptrauth_nop_ds3(ptr %p) { +; CHECK-LABEL: @test_ptrauth_nop_ds3( +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[P:%.*]] to i64 +; CHECK-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[TMP0]], i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds) ] +; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[SIGNED]], i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds2) ] +; CHECK-NEXT: ret i64 [[AUTHED]] +; + %tmp0 = ptrtoint ptr %p to i64 + %signed = call i64 @llvm.ptrauth.sign(i64 %tmp0, i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds) ] + %authed = call i64 @llvm.ptrauth.auth(i64 %signed, i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds2) ] + ret i64 %authed +} + +define i64 @test_ptrauth_nop_ds4(ptr %p) { +; CHECK-LABEL: @test_ptrauth_nop_ds4( +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[P:%.*]] to i64 +; CHECK-NEXT: ret i64 [[TMP0]] +; + %tmp0 = ptrtoint ptr %p to i64 + %signed = call i64 @llvm.ptrauth.sign(i64 %tmp0, i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds) ] + %authed = call i64 @llvm.ptrauth.auth(i64 %signed, i32 1, i64 1234) [ "deactivation-symbol"(ptr @ds) ] + ret i64 %authed +} + define i64 @test_ptrauth_nop_ds_constant() { ; CHECK-LABEL: @test_ptrauth_nop_ds_constant( ; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 ptrtoint (ptr ptrauth (ptr @foo, i32 1, i64 1234, ptr null, ptr @ds) to i64), i32 1, i64 1234) diff --git a/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll index bf60de446ea9..fbbae399f0ec 100644 --- a/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll +++ b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll @@ -1,23 +1,27 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -O2 -S < %s | FileCheck %s -; Test that no optimization run at -O2 moves the loads into the exit block, -; as this causes unnecessary address escapes with pointer field protection. +; Test that no optimization run at -O2 before InstCombine moves the loads into +; the exit block, as this causes unnecessary address escapes with pointer field +; protection. define ptr @phi_prot_ptr(i1 %sel, ptr %p1, ptr %p2) { ; CHECK-LABEL: define ptr @phi_prot_ptr( -; CHECK-SAME: i1 [[SEL:%.*]], ptr readonly [[P1:%.*]], ptr readonly [[P2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-SAME: i1 [[SEL:%.*]], ptr readonly captures(none) [[P1:%.*]], ptr readonly captures(none) [[P2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: br i1 [[SEL]], label %[[T:.*]], label %[[F:.*]] ; CHECK: [[T]]: -; CHECK-NEXT: [[PROTP1:%.*]] = tail call ptr @llvm.protected.field.ptr.p0(ptr [[P1]], i64 1, i1 true) -; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[PROTP1]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P1]], align 8 +; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; CHECK-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 1) ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[F]]: -; CHECK-NEXT: [[PROTP2:%.*]] = tail call ptr @llvm.protected.field.ptr.p0(ptr [[P2]], i64 2, i1 true) -; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[PROTP2]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[P2]], align 8 +; CHECK-NEXT: [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[TMP5]], i32 2, i64 2) ; CHECK-NEXT: br label %[[EXIT]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[RETVAL:%.*]] = phi ptr [ [[LOAD1]], %[[T]] ], [ [[LOAD2]], %[[F]] ] +; CHECK-NEXT: [[RETVAL_IN:%.*]] = phi i64 [ [[TMP3]], %[[T]] ], [ [[TMP6]], %[[F]] ] +; CHECK-NEXT: [[RETVAL:%.*]] = inttoptr i64 [[RETVAL_IN]] to ptr ; CHECK-NEXT: ret ptr [[RETVAL]] ; br i1 %sel, label %t, label %f diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/emupac.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/emupac.ll new file mode 100644 index 000000000000..310cacfcbfdf --- /dev/null +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/emupac.ll @@ -0,0 +1,64 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=pre-isel-intrinsic-lowering -mtriple aarch64-unknown-linux -S < %s | FileCheck --check-prefix=NOPAUTH %s +; RUN: opt -passes=pre-isel-intrinsic-lowering -mtriple aarch64-unknown-linux -mattr=+pauth -S < %s | FileCheck --check-prefix=PAUTH1 %s +; RUN: opt -passes=pre-isel-intrinsic-lowering -mtriple arm64e-apple-darwin -S < %s | FileCheck --check-prefix=PAUTH2 %s + +@ds = external global i8 + +define i64 @sign1(i64 %p) { +; NOPAUTH-LABEL: define i64 @sign1( +; NOPAUTH-SAME: i64 [[P:%.*]]) { +; NOPAUTH-NEXT: [[TMP1:%.*]] = call i64 @__emupac_autda(i64 [[P]], i64 1) +; NOPAUTH-NEXT: ret i64 [[TMP1]] +; +; PAUTH1-LABEL: define i64 @sign1( +; PAUTH1-SAME: i64 [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; PAUTH1-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 2, i64 1) +; PAUTH1-NEXT: ret i64 [[SIGNED]] +; +; PAUTH2-LABEL: define i64 @sign1( +; PAUTH2-SAME: i64 [[P:%.*]]) { +; PAUTH2-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 2, i64 1) +; PAUTH2-NEXT: ret i64 [[SIGNED]] +; + %signed = call i64 @llvm.ptrauth.auth(i64 %p, i32 2, i64 1) + ret i64 %signed +} +define i64 @sign2(i64 %p) { +; NOPAUTH-LABEL: define i64 @sign2( +; NOPAUTH-SAME: i64 [[P:%.*]]) { +; NOPAUTH-NEXT: [[TMP1:%.*]] = call i64 @__emupac_autda(i64 [[P]], i64 1) [ "deactivation-symbol"(ptr @ds) ] +; NOPAUTH-NEXT: ret i64 [[TMP1]] +; +; PAUTH1-LABEL: define i64 @sign2( +; PAUTH1-SAME: i64 [[P:%.*]]) #[[ATTR0]] { +; PAUTH1-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 2, i64 1) [ "deactivation-symbol"(ptr @ds) ] +; PAUTH1-NEXT: ret i64 [[SIGNED]] +; +; PAUTH2-LABEL: define i64 @sign2( +; PAUTH2-SAME: i64 [[P:%.*]]) { +; PAUTH2-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 2, i64 1) [ "deactivation-symbol"(ptr @ds) ] +; PAUTH2-NEXT: ret i64 [[SIGNED]] +; + %signed = call i64 @llvm.ptrauth.auth(i64 %p, i32 2, i64 1) [ "deactivation-symbol"(ptr @ds) ] + ret i64 %signed +} +define i64 @sign3(i64 %p) { +; NOPAUTH-LABEL: define i64 @sign3( +; NOPAUTH-SAME: i64 [[P:%.*]]) { +; NOPAUTH-NEXT: [[TMP1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 0, i64 1) [ "deactivation-symbol"(ptr @ds) ] +; NOPAUTH-NEXT: ret i64 [[TMP1]] +; +; PAUTH1-LABEL: define i64 @sign3( +; PAUTH1-SAME: i64 [[P:%.*]]) #[[ATTR0]] { +; PAUTH1-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 0, i64 1) [ "deactivation-symbol"(ptr @ds) ] +; PAUTH1-NEXT: ret i64 [[SIGNED]] +; +; PAUTH2-LABEL: define i64 @sign3( +; PAUTH2-SAME: i64 [[P:%.*]]) { +; PAUTH2-NEXT: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P]], i32 0, i64 1) [ "deactivation-symbol"(ptr @ds) ] +; PAUTH2-NEXT: ret i64 [[SIGNED]] +; + %signed = call i64 @llvm.ptrauth.auth(i64 %p, i32 0, i64 1) [ "deactivation-symbol"(ptr @ds) ] + ret i64 %signed +} diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer-addrspace1.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer-addrspace1.ll index f98807c25538..6783a15d1e9e 100644 --- a/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer-addrspace1.ll +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer-addrspace1.ll @@ -1,85 +1,25 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5 -; RUN: opt -passes=pre-isel-intrinsic-lowering -S < %s | FileCheck --check-prefix=NOPAUTH %s -; RUN: opt -passes=pre-isel-intrinsic-lowering -mattr=+pauth -S < %s | FileCheck --check-prefix=PAUTH %s +; RUN: opt -passes=pre-isel-intrinsic-lowering -mattr=+pauth -S < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" @ds1 = external global i8 @ds2 = external global i8 -@ds3 = external global i8 -@ds4 = external global i8 + ;. -; NOPAUTH: @ds1 = external global i8 -; NOPAUTH: @ds2 = external global i8 -; NOPAUTH: @ds3 = external global i8 -; NOPAUTH: @ds4 = hidden alias i8, inttoptr (i64 3573751839 to ptr) +; CHECK: @ds1 = external global i8 +; CHECK: @ds2 = hidden alias i8, inttoptr (i64 3573751839 to ptr) ;. -; PAUTH: @ds1 = external global i8 -; PAUTH: @ds2 = external global i8 -; PAUTH: @ds3 = external global i8 -; PAUTH: @ds4 = hidden alias i8, inttoptr (i64 3573751839 to ptr) -;. -define ptr @load_hw(ptr addrspace(1) %ptrptr) { -; NOPAUTH-LABEL: define ptr @load_hw( -; NOPAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: [[PTR:%.*]] = load ptr, ptr addrspace(1) [[PTRPTR]], align 8 -; NOPAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; NOPAUTH-NEXT: [[TMP2:%.*]] = call i64 @__emupac_autda(i64 [[TMP1]], i64 1) [ "deactivation-symbol"(ptr @ds1) ] -; NOPAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; NOPAUTH-NEXT: ret ptr [[TMP3]] -; -; PAUTH-LABEL: define ptr @load_hw( -; PAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) #[[ATTR0:[0-9]+]] { -; PAUTH-NEXT: [[PTR:%.*]] = load ptr, ptr addrspace(1) [[PTRPTR]], align 8 -; PAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; PAUTH-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 1) [ "deactivation-symbol"(ptr @ds1) ] -; PAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; PAUTH-NEXT: ret ptr [[TMP3]] -; - %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 1, i1 true) [ "deactivation-symbol"(ptr @ds1) ] - %ptr = load ptr, ptr addrspace(1) %protptrptr - ret ptr %ptr -} - -define void @store_hw(ptr addrspace(1) %ptrptr, ptr %ptr) { -; NOPAUTH-LABEL: define void @store_hw( -; NOPAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]], ptr [[PTR:%.*]]) { -; NOPAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; NOPAUTH-NEXT: [[TMP2:%.*]] = call i64 @__emupac_pacda(i64 [[TMP1]], i64 2) [ "deactivation-symbol"(ptr @ds2) ] -; NOPAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; NOPAUTH-NEXT: store ptr [[TMP3]], ptr addrspace(1) [[PTRPTR]], align 8 -; NOPAUTH-NEXT: ret void -; -; PAUTH-LABEL: define void @store_hw( -; PAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]], ptr [[PTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; PAUTH-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[TMP1]], i32 2, i64 2) [ "deactivation-symbol"(ptr @ds2) ] -; PAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; PAUTH-NEXT: store ptr [[TMP3]], ptr addrspace(1) [[PTRPTR]], align 8 -; PAUTH-NEXT: ret void -; - %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 2, i1 true) [ "deactivation-symbol"(ptr @ds2) ] - store ptr %ptr, ptr addrspace(1) %protptrptr - ret void -} - define i1 @compare(ptr addrspace(1) %ptrptr) { -; NOPAUTH-LABEL: define i1 @compare( -; NOPAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: [[CMP1:%.*]] = icmp eq ptr addrspace(1) [[PTRPTR]], null -; NOPAUTH-NEXT: [[CMP2:%.*]] = icmp eq ptr addrspace(1) null, [[PTRPTR]] -; NOPAUTH-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] -; NOPAUTH-NEXT: ret i1 [[CMP]] +; CHECK-LABEL: define i1 @compare( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr addrspace(1) [[PTRPTR]], null +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr addrspace(1) null, [[PTRPTR]] +; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: ret i1 [[CMP]] ; -; PAUTH-LABEL: define i1 @compare( -; PAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: [[CMP1:%.*]] = icmp eq ptr addrspace(1) [[PTRPTR]], null -; PAUTH-NEXT: [[CMP2:%.*]] = icmp eq ptr addrspace(1) null, [[PTRPTR]] -; PAUTH-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] -; PAUTH-NEXT: ret i1 [[CMP]] -; - %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds3) ] + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds1) ] %cmp1 = icmp eq ptr addrspace(1) %protptrptr, null %cmp2 = icmp eq ptr addrspace(1) null, %protptrptr %cmp = or i1 %cmp1, %cmp2 @@ -87,25 +27,16 @@ define i1 @compare(ptr addrspace(1) %ptrptr) { } define ptr addrspace(1) @escape(ptr addrspace(1) %ptrptr) { -; NOPAUTH-LABEL: define ptr addrspace(1) @escape( -; NOPAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: ret ptr addrspace(1) [[PTRPTR]] +; CHECK-LABEL: define ptr addrspace(1) @escape( +; CHECK-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret ptr addrspace(1) [[PTRPTR]] ; -; PAUTH-LABEL: define ptr addrspace(1) @escape( -; PAUTH-SAME: ptr addrspace(1) [[PTRPTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: ret ptr addrspace(1) [[PTRPTR]] -; - %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds4) ] + %protptrptr = call ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1) %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds2) ] ret ptr addrspace(1) %protptrptr } declare ptr addrspace(1) @llvm.protected.field.ptr.p1(ptr addrspace(1), i64, i1 immarg) ;. -; NOPAUTH: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } -; NOPAUTH: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(none) } -;. -; PAUTH: attributes #[[ATTR0]] = { "target-features"="+pauth" } -; PAUTH: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) "target-features"="+pauth" } -; PAUTH: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } -; PAUTH: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(none) } +; CHECK: attributes #[[ATTR0]] = { "target-features"="+pauth" } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) "target-features"="+pauth" } ;. diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer.ll index ba611fe4488b..1b42e505f49d 100644 --- a/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer.ll +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/protected-field-pointer.ll @@ -1,85 +1,25 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5 -; RUN: opt -passes=pre-isel-intrinsic-lowering -S < %s | FileCheck --check-prefix=NOPAUTH %s -; RUN: opt -passes=pre-isel-intrinsic-lowering -mattr=+pauth -S < %s | FileCheck --check-prefix=PAUTH %s +; RUN: opt -passes=pre-isel-intrinsic-lowering -mattr=+pauth -S < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" @ds1 = external global i8 @ds2 = external global i8 -@ds3 = external global i8 -@ds4 = external global i8 + ;. -; NOPAUTH: @ds1 = external global i8 -; NOPAUTH: @ds2 = external global i8 -; NOPAUTH: @ds3 = external global i8 -; NOPAUTH: @ds4 = hidden alias i8, inttoptr (i64 3573751839 to ptr) +; CHECK: @ds1 = external global i8 +; CHECK: @ds2 = hidden alias i8, inttoptr (i64 3573751839 to ptr) ;. -; PAUTH: @ds1 = external global i8 -; PAUTH: @ds2 = external global i8 -; PAUTH: @ds3 = external global i8 -; PAUTH: @ds4 = hidden alias i8, inttoptr (i64 3573751839 to ptr) -;. -define ptr @load_hw(ptr %ptrptr) { -; NOPAUTH-LABEL: define ptr @load_hw( -; NOPAUTH-SAME: ptr [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: [[PTR:%.*]] = load ptr, ptr [[PTRPTR]], align 8 -; NOPAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; NOPAUTH-NEXT: [[TMP2:%.*]] = call i64 @__emupac_autda(i64 [[TMP1]], i64 1) [ "deactivation-symbol"(ptr @ds1) ] -; NOPAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; NOPAUTH-NEXT: ret ptr [[TMP3]] -; -; PAUTH-LABEL: define ptr @load_hw( -; PAUTH-SAME: ptr [[PTRPTR:%.*]]) #[[ATTR0:[0-9]+]] { -; PAUTH-NEXT: [[PTR:%.*]] = load ptr, ptr [[PTRPTR]], align 8 -; PAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; PAUTH-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 1) [ "deactivation-symbol"(ptr @ds1) ] -; PAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; PAUTH-NEXT: ret ptr [[TMP3]] -; - %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 1, i1 true) [ "deactivation-symbol"(ptr @ds1) ] - %ptr = load ptr, ptr %protptrptr - ret ptr %ptr -} - -define void @store_hw(ptr %ptrptr, ptr %ptr) { -; NOPAUTH-LABEL: define void @store_hw( -; NOPAUTH-SAME: ptr [[PTRPTR:%.*]], ptr [[PTR:%.*]]) { -; NOPAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; NOPAUTH-NEXT: [[TMP2:%.*]] = call i64 @__emupac_pacda(i64 [[TMP1]], i64 2) [ "deactivation-symbol"(ptr @ds2) ] -; NOPAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; NOPAUTH-NEXT: store ptr [[TMP3]], ptr [[PTRPTR]], align 8 -; NOPAUTH-NEXT: ret void -; -; PAUTH-LABEL: define void @store_hw( -; PAUTH-SAME: ptr [[PTRPTR:%.*]], ptr [[PTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR]] to i64 -; PAUTH-NEXT: [[TMP2:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[TMP1]], i32 2, i64 2) [ "deactivation-symbol"(ptr @ds2) ] -; PAUTH-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr -; PAUTH-NEXT: store ptr [[TMP3]], ptr [[PTRPTR]], align 8 -; PAUTH-NEXT: ret void -; - %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 2, i1 true) [ "deactivation-symbol"(ptr @ds2) ] - store ptr %ptr, ptr %protptrptr - ret void -} - define i1 @compare(ptr %ptrptr) { -; NOPAUTH-LABEL: define i1 @compare( -; NOPAUTH-SAME: ptr [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: [[CMP1:%.*]] = icmp eq ptr [[PTRPTR]], null -; NOPAUTH-NEXT: [[CMP2:%.*]] = icmp eq ptr null, [[PTRPTR]] -; NOPAUTH-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] -; NOPAUTH-NEXT: ret i1 [[CMP]] +; CHECK-LABEL: define i1 @compare( +; CHECK-SAME: ptr [[PTRPTR:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[PTRPTR]], null +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr null, [[PTRPTR]] +; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: ret i1 [[CMP]] ; -; PAUTH-LABEL: define i1 @compare( -; PAUTH-SAME: ptr [[PTRPTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: [[CMP1:%.*]] = icmp eq ptr [[PTRPTR]], null -; PAUTH-NEXT: [[CMP2:%.*]] = icmp eq ptr null, [[PTRPTR]] -; PAUTH-NEXT: [[CMP:%.*]] = or i1 [[CMP1]], [[CMP2]] -; PAUTH-NEXT: ret i1 [[CMP]] -; - %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds3) ] + %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds1) ] %cmp1 = icmp eq ptr %protptrptr, null %cmp2 = icmp eq ptr null, %protptrptr %cmp = or i1 %cmp1, %cmp2 @@ -87,25 +27,16 @@ define i1 @compare(ptr %ptrptr) { } define ptr @escape(ptr %ptrptr) { -; NOPAUTH-LABEL: define ptr @escape( -; NOPAUTH-SAME: ptr [[PTRPTR:%.*]]) { -; NOPAUTH-NEXT: ret ptr [[PTRPTR]] +; CHECK-LABEL: define ptr @escape( +; CHECK-SAME: ptr [[PTRPTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret ptr [[PTRPTR]] ; -; PAUTH-LABEL: define ptr @escape( -; PAUTH-SAME: ptr [[PTRPTR:%.*]]) #[[ATTR0]] { -; PAUTH-NEXT: ret ptr [[PTRPTR]] -; - %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds4) ] + %protptrptr = call ptr @llvm.protected.field.ptr.p0(ptr %ptrptr, i64 3, i1 true) [ "deactivation-symbol"(ptr @ds2) ] ret ptr %protptrptr } declare ptr @llvm.protected.field.ptr.p0(ptr, i64, i1 immarg) ;. -; NOPAUTH: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } -; NOPAUTH: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(none) } -;. -; PAUTH: attributes #[[ATTR0]] = { "target-features"="+pauth" } -; PAUTH: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) "target-features"="+pauth" } -; PAUTH: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } -; PAUTH: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(none) } +; CHECK: attributes #[[ATTR0]] = { "target-features"="+pauth" } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) "target-features"="+pauth" } ;.