[llvm-branch-commits] [llvm] [AArch64][PAC] Combine signing with address materialization (PR #130809)
Anatoly Trosinenko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jul 23 10:26:59 PDT 2025
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/130809
>From 43fcb8009c99fe50563c3dde3ab146ef94d0713d Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Mon, 10 Mar 2025 15:14:55 +0300
Subject: [PATCH 1/3] [AArch64][PAC] Precommit tests on merging
MOVaddr/LOADgotAUTH with PAC*
---
.../GlobalISel/ptrauth-constant-in-code.ll | 76 +++++++++++++++++++
.../AArch64/ptrauth-constant-in-code.ll | 71 +++++++++++++++++
2 files changed, 147 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
index 12a3448111fcb..718c799676b32 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
@@ -78,6 +78,82 @@ define ptr @foo() {
ret ptr ptrauth (ptr @g, i32 0)
}
+;--- finalize-isel.ll
+
+; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \
+; RUN: FileCheck --check-prefixes=ISEL,ISEL-ELF %s
+; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \
+; RUN: FileCheck --check-prefixes=ISEL %s
+
+ at const_table_local = dso_local constant [3 x ptr] [ptr null, ptr null, ptr null]
+ at const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+
+define void @store_signed_const_local(ptr %dest) {
+; ISEL-LABEL: name: store_signed_const_local
+; ISEL: body:
+; ISEL: %0:gpr64common = COPY $x0
+; ISEL-NEXT: %10:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
+; ISEL-NEXT: %2:gpr64noip = MOVKXi %0, 1234
+; ISEL-NEXT: %15:gpr64noip = COPY %0
+; ISEL-NEXT: %4:gpr64 = PAC %10, 2, 1234, %15, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-NEXT: %14:gpr64 = COPY %4
+; ISEL-NEXT: STRXui %14, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_local, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+define void @store_signed_const_got(ptr %dest) {
+; ISEL-ELF-LABEL: name: store_signed_const_got
+; ISEL-ELF: body:
+; ISEL-ELF: %0:gpr64common = COPY $x0
+; ISEL-ELF-NEXT: %7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got
+; ISEL-ELF-NEXT: %6:gpr64common = ADDXri %7, 8, 0
+; ISEL-ELF-NEXT: %2:gpr64noip = MOVKXi %0, 1234
+; ISEL-ELF-NEXT: %12:gpr64noip = COPY %0
+; ISEL-ELF-NEXT: %4:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-ELF-NEXT: %10:gpr64 = COPY %4
+; ISEL-ELF-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-ELF-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+define void @store_signed_arg(ptr %dest, ptr %p) {
+; ISEL-LABEL: name: store_signed_arg
+; ISEL: body:
+; ISEL: %0:gpr64common = COPY $x0
+; ISEL-NEXT: %1:gpr64common = COPY $x1
+; ISEL-NEXT: %3:gpr64noip = MOVKXi %0, 1234
+; ISEL-NEXT: %6:gpr64common = ADDXri %1, 8, 0
+; ISEL-NEXT: %12:gpr64noip = COPY %0
+; ISEL-NEXT: %8:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-NEXT: %10:gpr64 = COPY %8
+; ISEL-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %p.offset = getelementptr [2 x ptr], ptr %p, i32 0, i32 1
+ %p.offset.i = ptrtoint ptr %p.offset to i64
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 %p.offset.i, i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
+
;--- ok.ll
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
index 76339a7cc5791..3aa5ba9260063 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
@@ -69,6 +69,77 @@ define ptr @foo() {
ret ptr ptrauth (ptr @g, i32 0)
}
+;--- finalize-isel.ll
+
+; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL,ISEL-ELF %s
+; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL %s
+
+ at const_table_local = dso_local constant [3 x ptr] [ptr null, ptr null, ptr null]
+ at const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+
+define void @store_signed_const_local(ptr %dest) {
+; ISEL-LABEL: name: store_signed_const_local
+; ISEL: body:
+; ISEL: %0:gpr64common = COPY $x0
+; ISEL-NEXT: %1:gpr64noip = MOVKXi %0, 1234
+; ISEL-NEXT: %2:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
+; ISEL-NEXT: %4:gpr64noip = COPY %0
+; ISEL-NEXT: %3:gpr64 = PAC %2, 2, 1234, killed %4, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-NEXT: STRXui killed %3, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_local, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+define void @store_signed_const_got(ptr %dest) {
+; ISEL-ELF-LABEL: name: store_signed_const_got
+; ISEL-ELF: body:
+; ISEL-ELF: %0:gpr64common = COPY $x0
+; ISEL-ELF-NEXT: %1:gpr64noip = MOVKXi %0, 1234
+; ISEL-ELF-NEXT: %2:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $nzcv
+; ISEL-ELF-NEXT: %3:gpr64common = ADDXri killed %2, 8, 0
+; ISEL-ELF-NEXT: %5:gpr64noip = COPY %0
+; ISEL-ELF-NEXT: %4:gpr64 = PAC %3, 2, 1234, killed %5, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-ELF-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-ELF-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+define void @store_signed_arg(ptr %dest, ptr %p) {
+; ISEL-LABEL: name: store_signed_arg
+; ISEL: body:
+; ISEL: %1:gpr64common = COPY $x1
+; ISEL-NEXT: %0:gpr64common = COPY $x0
+; ISEL-NEXT: %2:gpr64noip = MOVKXi %0, 1234
+; ISEL-NEXT: %3:gpr64common = ADDXri %1, 8, 0
+; ISEL-NEXT: %5:gpr64noip = COPY %0
+; ISEL-NEXT: %4:gpr64 = PAC %3, 2, 1234, killed %5, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-NEXT: RET_ReallyLR
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %p.offset = getelementptr [2 x ptr], ptr %p, i32 0, i32 1
+ %p.offset.i = ptrtoint ptr %p.offset to i64
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 %p.offset.i, i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
+
;--- ok.ll
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
>From fe747bef940eb96059d05d47d77abfb590a799f7 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Mon, 30 Jun 2025 19:19:13 +0300
Subject: [PATCH 2/3] [AArch64][PAC] Combine signing with address
materialization
In pauthtest ABI, it is common to store a pointer signed with address
diversity to a heap-allocated object (namely, storing a signed pointer
to VTable as part of new object construction). This patch tries to
prevent introducing a signing oracle by combining pointer
materialization and its (re)signing into a single pseudo instruction
which is not expanded until AsmPrinter, if possible.
One of the typical patterns is materializing an unsigned pointer with
`MOVaddr` pseudo and then signing it with `PAC[ID][AB]` instruction,
which can be moved far away from `MOVaddr` by one of the passes in the
machine pipeline. As the storage address is not a `Constant` value, one
cannot simply emit a `ptrauth` constant in the frontend, which would be
selected into `MOVaddrPAC` pseudo.
Another pattern is fetching a pointer to VTable from a signed GOT entry
using `LOADgotAUTH` pseudo, authenticating and checking it, and then
re-signing after adding an offset.
This commit adds an instruction insertion hook for `PAC[ID][AB]` which
detects the above patterns and replaces it either with `MOVaddrPAC` or
`LOADgotPAC` instruction.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 81 ++++++++++--
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 3 +
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 3 +
.../GlobalISel/ptrauth-constant-in-code.ll | 122 +++++++++++++-----
.../AArch64/ptrauth-constant-in-code.ll | 114 +++++++++++-----
.../CodeGen/AArch64/ptrauth-tiny-model-pic.ll | 4 +-
.../AArch64/ptrauth-tiny-model-static.ll | 4 +-
7 files changed, 254 insertions(+), 77 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 1956294f7daa8..3545b73a7833b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3098,10 +3098,13 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
return BB;
}
-// Helper function to find the instruction that defined a virtual register.
-// If unable to find such instruction, returns nullptr.
-static const MachineInstr *stripVRegCopies(const MachineRegisterInfo &MRI,
- Register Reg) {
+// Helper function to find the instruction that defined a virtual register,
+// stripping and accumulating optional offset.
+// If unable to find such instruction, returns nullptr (Offset is unspecified).
+static const MachineInstr *
+stripAndAccumulateOffset(const MachineRegisterInfo &MRI, Register Reg,
+ int64_t &Offset) {
+ Offset = 0;
while (Reg.isVirtual()) {
MachineInstr *DefMI = MRI.getVRegDef(Reg);
assert(DefMI && "Virtual register definition not found");
@@ -3119,7 +3122,17 @@ static const MachineInstr *stripVRegCopies(const MachineRegisterInfo &MRI,
continue;
}
- return DefMI;
+ // If this is neither a copy, nor inc/dec instruction, we are done.
+ if (Opcode != AArch64::ADDXri && Opcode != AArch64::SUBXri)
+ return DefMI;
+ // Inc/dec with shifted immediates are not handled.
+ if (DefMI->getOperand(3).getImm() != 0)
+ return DefMI;
+
+ int64_t Imm = DefMI->getOperand(2).getImm();
+ Offset += (Opcode == AArch64::ADDXri) ? Imm : -Imm;
+
+ Reg = DefMI->getOperand(1).getReg();
}
return nullptr;
}
@@ -3135,8 +3148,13 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator(
int64_t IntDisc = IntDiscOp.getImm();
assert(IntDisc == 0 && "Blend components are already expanded");
- const MachineInstr *DiscMI = stripVRegCopies(MRI, AddrDisc);
- if (DiscMI) {
+ int64_t Offset = 0;
+ const MachineInstr *DiscMI = stripAndAccumulateOffset(MRI, AddrDisc, Offset);
+
+ // The result of any recognized discriminator computation may be copied, but
+ // without adding any offset. Nevertheless, perform the remaining fix-ups
+ // even on an opaque, pre-computed discriminator.
+ if (DiscMI && Offset == 0) {
switch (DiscMI->getOpcode()) {
case AArch64::MOVKXi:
// blend(addr, imm) which is lowered as "MOVK addr, #imm, #48".
@@ -3175,6 +3193,53 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator(
IntDiscOp.setImm(IntDisc);
}
+MachineBasicBlock *
+AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
+ const TargetInstrInfo *TII = Subtarget->getInstrInfo();
+ MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
+ const DebugLoc &DL = MI.getDebugLoc();
+
+ Register Val = MI.getOperand(1).getReg();
+ unsigned Key = MI.getOperand(2).getImm();
+ int64_t IntDisc = MI.getOperand(3).getImm();
+ Register AddrDisc = MI.getOperand(4).getReg();
+
+ // Try to find a known address-setting instruction, accumulating the offset
+ // along the way. If no known pattern is found, keep everything as-is.
+
+ int64_t AddrOffset = 0;
+ const MachineInstr *AddrDefInstr =
+ stripAndAccumulateOffset(MRI, Val, AddrOffset);
+ if (!AddrDefInstr)
+ return BB;
+
+ unsigned NewOpcode;
+ if (AddrDefInstr->getOpcode() == AArch64::LOADgotAUTH)
+ NewOpcode = AArch64::LOADgotPAC;
+ else if (AddrDefInstr->getOpcode() == AArch64::MOVaddr)
+ NewOpcode = AArch64::MOVaddrPAC;
+ else
+ return BB; // Unknown opcode.
+
+ const MachineOperand &AddrOp = AddrDefInstr->getOperand(1);
+ unsigned TargetFlags = AddrOp.getTargetFlags() & ~AArch64II::MO_PAGE;
+ const GlobalValue *GV = AddrOp.getGlobal();
+ AddrOffset += AddrOp.getOffset();
+
+ BuildMI(*BB, MI, DL, TII->get(NewOpcode))
+ .addGlobalAddress(GV, AddrOffset, TargetFlags)
+ .addImm(Key)
+ .addReg(AddrDisc)
+ .addImm(IntDisc);
+
+ BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), MI.getOperand(0).getReg())
+ .addReg(AArch64::X16);
+
+ MI.removeFromParent();
+ return BB;
+}
+
MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
MachineInstr &MI, MachineBasicBlock *BB) const {
@@ -3285,7 +3350,7 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
case AArch64::PAC:
fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4),
&AArch64::GPR64noipRegClass);
- return BB;
+ return tryRewritingPAC(MI, BB);
case AArch64::AUTPAC:
fixupPtrauthDiscriminator(MI, BB, MI.getOperand(1), MI.getOperand(2),
&AArch64::GPR64noipRegClass);
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 4d3dee98c1f44..1c7ba3a73f981 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -189,6 +189,9 @@ class AArch64TargetLowering : public TargetLowering {
MachineOperand &AddrDiscOp,
const TargetRegisterClass *AddrDiscRC) const;
+ MachineBasicBlock *tryRewritingPAC(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
+
MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index faec98f47d895..a9bed163d7383 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2217,6 +2217,9 @@ let Predicates = [HasPAuth] in {
def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>,
Sched<[WriteI, ReadI]> {
+ // Make it possible to eliminate dead instruction after folding it
+ // into LOADgotPAC.
+ let hasSideEffects = 0;
let Defs = [X16,X17,NZCV];
let Size = 44;
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
index 718c799676b32..de0d954cd1c5b 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
@@ -82,25 +82,50 @@ define ptr @foo() {
; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \
-; RUN: FileCheck --check-prefixes=ISEL,ISEL-ELF %s
+; RUN: FileCheck --check-prefixes=ISEL-MIR,ISEL-MIR-ELF %s
; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \
; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \
-; RUN: FileCheck --check-prefixes=ISEL %s
+; RUN: FileCheck --check-prefixes=ISEL-MIR %s
+; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -asm-verbose=0 | \
+; RUN: FileCheck --check-prefixes=ISEL-ASM,ISEL-ASM-ELF %s
+; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -asm-verbose=0 | \
+; RUN: FileCheck --check-prefixes=ISEL-ASM,ISEL-ASM-MACHO %s
@const_table_local = dso_local constant [3 x ptr] [ptr null, ptr null, ptr null]
@const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+; Test that after post-processing in finalize-isel, MOVaddrPAC (or LOADgotPAC,
+; respectively) has both $AddrDisc and $Disc operands set. MOVaddr (or LOADgotAUTH,
+; respectively) and MOVKXi are not used anymore and are dead-code-eliminated
+; by the later passes.
+
define void @store_signed_const_local(ptr %dest) {
-; ISEL-LABEL: name: store_signed_const_local
-; ISEL: body:
-; ISEL: %0:gpr64common = COPY $x0
-; ISEL-NEXT: %10:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
-; ISEL-NEXT: %2:gpr64noip = MOVKXi %0, 1234
-; ISEL-NEXT: %15:gpr64noip = COPY %0
-; ISEL-NEXT: %4:gpr64 = PAC %10, 2, 1234, %15, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-NEXT: %14:gpr64 = COPY %4
-; ISEL-NEXT: STRXui %14, %0, 0 :: (store (p0) into %ir.dest)
-; ISEL-NEXT: RET_ReallyLR
+; ISEL-MIR-LABEL: name: store_signed_const_local
+; ISEL-MIR: body:
+; ISEL-MIR: %0:gpr64common = COPY $x0
+; ISEL-MIR-NEXT: %10:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
+; ISEL-MIR-NEXT: %2:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-NEXT: %15:gpr64noip = COPY %0
+; ISEL-MIR-NEXT: MOVaddrPAC @const_table_local + 8, 2, %15, 1234, implicit-def $x16, implicit-def $x17
+; ISEL-MIR-NEXT: %4:gpr64 = COPY $x16
+; ISEL-MIR-NEXT: %14:gpr64 = COPY %4
+; ISEL-MIR-NEXT: STRXui %14, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-LABEL: store_signed_const_local:
+; ISEL-ASM-NEXT: .cfi_startproc
+; ISEL-ASM-ELF-NEXT: adrp x16, const_table_local
+; ISEL-ASM-ELF-NEXT: add x16, x16, :lo12:const_table_local
+; ISEL-ASM-MACHO-NEXT: adrp x16, _const_table_local at PAGE
+; ISEL-ASM-MACHO-NEXT: add x16, x16, _const_table_local at PAGEOFF
+; ISEL-ASM-NEXT: add x16, x16, #8
+; ISEL-ASM-NEXT: mov x17, x0
+; ISEL-ASM-NEXT: movk x17, #1234, lsl #48
+; ISEL-ASM-NEXT: pacda x16, x17
+; ISEL-ASM-NEXT: str x16, [x0]
+; ISEL-ASM-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_local, i32 0, i32 1) to i64), i32 2, i64 %discr)
@@ -110,17 +135,37 @@ define void @store_signed_const_local(ptr %dest) {
}
define void @store_signed_const_got(ptr %dest) {
-; ISEL-ELF-LABEL: name: store_signed_const_got
-; ISEL-ELF: body:
-; ISEL-ELF: %0:gpr64common = COPY $x0
-; ISEL-ELF-NEXT: %7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got
-; ISEL-ELF-NEXT: %6:gpr64common = ADDXri %7, 8, 0
-; ISEL-ELF-NEXT: %2:gpr64noip = MOVKXi %0, 1234
-; ISEL-ELF-NEXT: %12:gpr64noip = COPY %0
-; ISEL-ELF-NEXT: %4:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-ELF-NEXT: %10:gpr64 = COPY %4
-; ISEL-ELF-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
-; ISEL-ELF-NEXT: RET_ReallyLR
+; ISEL-MIR-ELF-LABEL: name: store_signed_const_got
+; ISEL-MIR-ELF: body:
+; ISEL-MIR-ELF: %0:gpr64common = COPY $x0
+; ISEL-MIR-ELF-NEXT: %7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got
+; ISEL-MIR-ELF-NEXT: %6:gpr64common = ADDXri %7, 8, 0
+; ISEL-MIR-ELF-NEXT: %2:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-ELF-NEXT: %12:gpr64noip = COPY %0
+; ISEL-MIR-ELF-NEXT: LOADgotPAC target-flags(aarch64-got) @const_table_got + 8, 2, %12, 1234, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
+; ISEL-MIR-ELF-NEXT: %4:gpr64 = COPY $x16
+; ISEL-MIR-ELF-NEXT: %10:gpr64 = COPY %4
+; ISEL-MIR-ELF-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-MIR-ELF-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-ELF-LABEL: store_signed_const_got:
+; ISEL-ASM-ELF-NEXT: .cfi_startproc
+; ISEL-ASM-ELF-NEXT: adrp x17, :got_auth:const_table_got
+; ISEL-ASM-ELF-NEXT: add x17, x17, :got_auth_lo12:const_table_got
+; ISEL-ASM-ELF-NEXT: ldr x16, [x17]
+; ISEL-ASM-ELF-NEXT: autda x16, x17
+; ISEL-ASM-ELF-NEXT: mov x17, x16
+; ISEL-ASM-ELF-NEXT: xpacd x17
+; ISEL-ASM-ELF-NEXT: cmp x16, x17
+; ISEL-ASM-ELF-NEXT: b.eq .Lauth_success_0
+; ISEL-ASM-ELF-NEXT: brk #0xc472
+; ISEL-ASM-ELF-NEXT: .Lauth_success_0:
+; ISEL-ASM-ELF-NEXT: add x16, x16, #8
+; ISEL-ASM-ELF-NEXT: mov x17, x0
+; ISEL-ASM-ELF-NEXT: movk x17, #1234, lsl #48
+; ISEL-ASM-ELF-NEXT: pacda x16, x17
+; ISEL-ASM-ELF-NEXT: str x16, [x0]
+; ISEL-ASM-ELF-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
@@ -130,17 +175,26 @@ define void @store_signed_const_got(ptr %dest) {
}
define void @store_signed_arg(ptr %dest, ptr %p) {
-; ISEL-LABEL: name: store_signed_arg
-; ISEL: body:
-; ISEL: %0:gpr64common = COPY $x0
-; ISEL-NEXT: %1:gpr64common = COPY $x1
-; ISEL-NEXT: %3:gpr64noip = MOVKXi %0, 1234
-; ISEL-NEXT: %6:gpr64common = ADDXri %1, 8, 0
-; ISEL-NEXT: %12:gpr64noip = COPY %0
-; ISEL-NEXT: %8:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-NEXT: %10:gpr64 = COPY %8
-; ISEL-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
-; ISEL-NEXT: RET_ReallyLR
+; ISEL-MIR-LABEL: name: store_signed_arg
+; ISEL-MIR: body:
+; ISEL-MIR: %0:gpr64common = COPY $x0
+; ISEL-MIR-NEXT: %1:gpr64common = COPY $x1
+; ISEL-MIR-NEXT: %3:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-NEXT: %6:gpr64common = ADDXri %1, 8, 0
+; ISEL-MIR-NEXT: %12:gpr64noip = COPY %0
+; ISEL-MIR-NEXT: %8:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-MIR-NEXT: %10:gpr64 = COPY %8
+; ISEL-MIR-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-LABEL: store_signed_arg:
+; ISEL-ASM-NEXT: .cfi_startproc
+; ISEL-ASM-NEXT: add x8, x1, #8
+; ISEL-ASM-NEXT: mov x16, x0
+; ISEL-ASM-NEXT: movk x16, #1234, lsl #48
+; ISEL-ASM-NEXT: pacda x8, x16
+; ISEL-ASM-NEXT: str x8, [x0]
+; ISEL-ASM-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%p.offset = getelementptr [2 x ptr], ptr %p, i32 0, i32 1
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
index 3aa5ba9260063..84ce66b18fa51 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
@@ -72,23 +72,46 @@ define ptr @foo() {
;--- finalize-isel.ll
; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
-; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL,ISEL-ELF %s
+; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL-MIR,ISEL-MIR-ELF %s
; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \
-; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL %s
+; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL-MIR %s
+; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -asm-verbose=0 | FileCheck --check-prefixes=ISEL-ASM,ISEL-ASM-ELF %s
+; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -asm-verbose=0 | FileCheck --check-prefixes=ISEL-ASM,ISEL-ASM-MACHO %s
@const_table_local = dso_local constant [3 x ptr] [ptr null, ptr null, ptr null]
@const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+; Test that after post-processing in finalize-isel, MOVaddrPAC (or LOADgotPAC,
+; respectively) has both $AddrDisc and $Disc operands set. MOVaddr (or LOADgotAUTH,
+; respectively) and MOVKXi are not used anymore and are dead-code-eliminated
+; by the later passes.
+
define void @store_signed_const_local(ptr %dest) {
-; ISEL-LABEL: name: store_signed_const_local
-; ISEL: body:
-; ISEL: %0:gpr64common = COPY $x0
-; ISEL-NEXT: %1:gpr64noip = MOVKXi %0, 1234
-; ISEL-NEXT: %2:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
-; ISEL-NEXT: %4:gpr64noip = COPY %0
-; ISEL-NEXT: %3:gpr64 = PAC %2, 2, 1234, killed %4, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-NEXT: STRXui killed %3, %0, 0 :: (store (s64) into %ir.dest)
-; ISEL-NEXT: RET_ReallyLR
+; ISEL-MIR-LABEL: name: store_signed_const_local
+; ISEL-MIR: body:
+; ISEL-MIR: %0:gpr64common = COPY $x0
+; ISEL-MIR-NEXT: %1:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-NEXT: %2:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8
+; ISEL-MIR-NEXT: %4:gpr64noip = COPY %0
+; ISEL-MIR-NEXT: MOVaddrPAC @const_table_local + 8, 2, %4, 1234, implicit-def $x16, implicit-def $x17
+; ISEL-MIR-NEXT: %3:gpr64 = COPY $x16
+; ISEL-MIR-NEXT: STRXui killed %3, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-LABEL: store_signed_const_local:
+; ISEL-ASM-NEXT: .cfi_startproc
+; ISEL-ASM-ELF-NEXT: adrp x16, const_table_local
+; ISEL-ASM-ELF-NEXT: add x16, x16, :lo12:const_table_local
+; ISEL-ASM-MACHO-NEXT: adrp x16, _const_table_local at PAGE
+; ISEL-ASM-MACHO-NEXT: add x16, x16, _const_table_local at PAGEOFF
+; ISEL-ASM-NEXT: add x16, x16, #8
+; ISEL-ASM-NEXT: mov x17, x0
+; ISEL-ASM-NEXT: movk x17, #1234, lsl #48
+; ISEL-ASM-NEXT: pacda x16, x17
+; ISEL-ASM-NEXT: str x16, [x0]
+; ISEL-ASM-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_local, i32 0, i32 1) to i64), i32 2, i64 %discr)
@@ -98,16 +121,36 @@ define void @store_signed_const_local(ptr %dest) {
}
define void @store_signed_const_got(ptr %dest) {
-; ISEL-ELF-LABEL: name: store_signed_const_got
-; ISEL-ELF: body:
-; ISEL-ELF: %0:gpr64common = COPY $x0
-; ISEL-ELF-NEXT: %1:gpr64noip = MOVKXi %0, 1234
-; ISEL-ELF-NEXT: %2:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $nzcv
-; ISEL-ELF-NEXT: %3:gpr64common = ADDXri killed %2, 8, 0
-; ISEL-ELF-NEXT: %5:gpr64noip = COPY %0
-; ISEL-ELF-NEXT: %4:gpr64 = PAC %3, 2, 1234, killed %5, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-ELF-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
-; ISEL-ELF-NEXT: RET_ReallyLR
+; ISEL-MIR-ELF-LABEL: name: store_signed_const_got
+; ISEL-MIR-ELF: body:
+; ISEL-MIR-ELF: %0:gpr64common = COPY $x0
+; ISEL-MIR-ELF-NEXT: %1:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-ELF-NEXT: %2:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $nzcv
+; ISEL-MIR-ELF-NEXT: %3:gpr64common = ADDXri killed %2, 8, 0
+; ISEL-MIR-ELF-NEXT: %5:gpr64noip = COPY %0
+; ISEL-MIR-ELF-NEXT: LOADgotPAC target-flags(aarch64-got) @const_table_got + 8, 2, %5, 1234, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
+; ISEL-MIR-ELF-NEXT: %4:gpr64 = COPY $x16
+; ISEL-MIR-ELF-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-MIR-ELF-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-ELF-LABEL: store_signed_const_got:
+; ISEL-ASM-ELF-NEXT: .cfi_startproc
+; ISEL-ASM-ELF-NEXT: adrp x17, :got_auth:const_table_got
+; ISEL-ASM-ELF-NEXT: add x17, x17, :got_auth_lo12:const_table_got
+; ISEL-ASM-ELF-NEXT: ldr x16, [x17]
+; ISEL-ASM-ELF-NEXT: autda x16, x17
+; ISEL-ASM-ELF-NEXT: mov x17, x16
+; ISEL-ASM-ELF-NEXT: xpacd x17
+; ISEL-ASM-ELF-NEXT: cmp x16, x17
+; ISEL-ASM-ELF-NEXT: b.eq .Lauth_success_0
+; ISEL-ASM-ELF-NEXT: brk #0xc472
+; ISEL-ASM-ELF-NEXT: .Lauth_success_0:
+; ISEL-ASM-ELF-NEXT: add x16, x16, #8
+; ISEL-ASM-ELF-NEXT: mov x17, x0
+; ISEL-ASM-ELF-NEXT: movk x17, #1234, lsl #48
+; ISEL-ASM-ELF-NEXT: pacda x16, x17
+; ISEL-ASM-ELF-NEXT: str x16, [x0]
+; ISEL-ASM-ELF-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
@@ -117,16 +160,25 @@ define void @store_signed_const_got(ptr %dest) {
}
define void @store_signed_arg(ptr %dest, ptr %p) {
-; ISEL-LABEL: name: store_signed_arg
-; ISEL: body:
-; ISEL: %1:gpr64common = COPY $x1
-; ISEL-NEXT: %0:gpr64common = COPY $x0
-; ISEL-NEXT: %2:gpr64noip = MOVKXi %0, 1234
-; ISEL-NEXT: %3:gpr64common = ADDXri %1, 8, 0
-; ISEL-NEXT: %5:gpr64noip = COPY %0
-; ISEL-NEXT: %4:gpr64 = PAC %3, 2, 1234, killed %5, implicit-def dead $x16, implicit-def dead $x17
-; ISEL-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
-; ISEL-NEXT: RET_ReallyLR
+; ISEL-MIR-LABEL: name: store_signed_arg
+; ISEL-MIR: body:
+; ISEL-MIR: %1:gpr64common = COPY $x1
+; ISEL-MIR-NEXT: %0:gpr64common = COPY $x0
+; ISEL-MIR-NEXT: %2:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-MIR-NEXT: %3:gpr64common = ADDXri %1, 8, 0
+; ISEL-MIR-NEXT: %5:gpr64noip = COPY %0
+; ISEL-MIR-NEXT: %4:gpr64 = PAC %3, 2, 1234, killed %5, implicit-def dead $x16, implicit-def dead $x17
+; ISEL-MIR-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ASM-LABEL: store_signed_arg:
+; ISEL-ASM-NEXT: .cfi_startproc
+; ISEL-ASM-NEXT: add x8, x1, #8
+; ISEL-ASM-NEXT: mov x16, x0
+; ISEL-ASM-NEXT: movk x16, #1234, lsl #48
+; ISEL-ASM-NEXT: pacda x8, x16
+; ISEL-ASM-NEXT: str x8, [x0]
+; ISEL-ASM-NEXT: ret
%dest.i = ptrtoint ptr %dest to i64
%discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
%p.offset = getelementptr [2 x ptr], ptr %p, i32 0, i32 1
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
index 9d13714bbefe3..cb8f1f4021eea 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
@@ -34,7 +34,6 @@ define dso_preemptable void @foo1() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_0:
; TRAP-NEXT: mov x8, x16
-; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: adr x17, :got_auth:dst
; NOTRAP-NEXT: ldr x9, [x17]
; NOTRAP-NEXT: autda x9, x17
@@ -47,6 +46,7 @@ define dso_preemptable void @foo1() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_1:
; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: strb w8, [x9]
; CHECK-NEXT: ret
@@ -106,7 +106,6 @@ define dso_preemptable void @foo3() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_4:
; TRAP-NEXT: mov x8, x16
-; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: adr x17, :got_auth:ptr
; NOTRAP-NEXT: ldr x9, [x17]
; NOTRAP-NEXT: autda x9, x17
@@ -119,6 +118,7 @@ define dso_preemptable void @foo3() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_5:
; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: ldr x9, [x9]
; CHECK-NEXT: strb w8, [x9]
; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
index 2d098b70acccc..0bf54ab49381e 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
@@ -34,7 +34,6 @@ define dso_local void @foo1() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_0:
; TRAP-NEXT: mov x8, x16
-; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: adr x17, :got_auth:dst
; NOTRAP-NEXT: ldr x9, [x17]
; NOTRAP-NEXT: autda x9, x17
@@ -47,6 +46,7 @@ define dso_local void @foo1() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_1:
; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: strb w8, [x9]
; CHECK-NEXT: ret
@@ -106,7 +106,6 @@ define dso_local void @foo3() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_4:
; TRAP-NEXT: mov x8, x16
-; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: adr x17, :got_auth:ptr
; NOTRAP-NEXT: ldr x9, [x17]
; NOTRAP-NEXT: autda x9, x17
@@ -119,6 +118,7 @@ define dso_local void @foo3() {
; TRAP-NEXT: brk #0xc472
; TRAP-NEXT: .Lauth_success_5:
; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldrb w8, [x8]
; CHECK-NEXT: ldr x9, [x9]
; CHECK-NEXT: strb w8, [x9]
; CHECK-NEXT: ret
>From 0597818acc9569596113a854e11dd3fe57a833f7 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Wed, 23 Jul 2025 19:42:08 +0300
Subject: [PATCH 3/3] Transform LOADgot in addition to LOADgotAUTH
---
.../Target/AArch64/AArch64ISelLowering.cpp | 3 +-
.../GlobalISel/ptrauth-constant-in-code.ll | 68 ++++++++++++++++---
.../AArch64/ptrauth-constant-in-code.ll | 65 +++++++++++++++---
3 files changed, 113 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 3545b73a7833b..225aa162adf69 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3215,7 +3215,8 @@ AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
return BB;
unsigned NewOpcode;
- if (AddrDefInstr->getOpcode() == AArch64::LOADgotAUTH)
+ if (AddrDefInstr->getOpcode() == AArch64::LOADgot ||
+ AddrDefInstr->getOpcode() == AArch64::LOADgotAUTH)
NewOpcode = AArch64::LOADgotPAC;
else if (AddrDefInstr->getOpcode() == AArch64::MOVaddr)
NewOpcode = AArch64::MOVaddrPAC;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
index de0d954cd1c5b..766c34b142e13 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
@@ -138,7 +138,7 @@ define void @store_signed_const_got(ptr %dest) {
; ISEL-MIR-ELF-LABEL: name: store_signed_const_got
; ISEL-MIR-ELF: body:
; ISEL-MIR-ELF: %0:gpr64common = COPY $x0
-; ISEL-MIR-ELF-NEXT: %7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got
+; ISEL-MIR-ELF-NEXT: %7:gpr64common = LOADgot target-flags(aarch64-got) @const_table_got
; ISEL-MIR-ELF-NEXT: %6:gpr64common = ADDXri %7, 8, 0
; ISEL-MIR-ELF-NEXT: %2:gpr64noip = MOVKXi %0, 1234, 48
; ISEL-MIR-ELF-NEXT: %12:gpr64noip = COPY %0
@@ -150,16 +150,8 @@ define void @store_signed_const_got(ptr %dest) {
;
; ISEL-ASM-ELF-LABEL: store_signed_const_got:
; ISEL-ASM-ELF-NEXT: .cfi_startproc
-; ISEL-ASM-ELF-NEXT: adrp x17, :got_auth:const_table_got
-; ISEL-ASM-ELF-NEXT: add x17, x17, :got_auth_lo12:const_table_got
-; ISEL-ASM-ELF-NEXT: ldr x16, [x17]
-; ISEL-ASM-ELF-NEXT: autda x16, x17
-; ISEL-ASM-ELF-NEXT: mov x17, x16
-; ISEL-ASM-ELF-NEXT: xpacd x17
-; ISEL-ASM-ELF-NEXT: cmp x16, x17
-; ISEL-ASM-ELF-NEXT: b.eq .Lauth_success_0
-; ISEL-ASM-ELF-NEXT: brk #0xc472
-; ISEL-ASM-ELF-NEXT: .Lauth_success_0:
+; ISEL-ASM-ELF-NEXT: adrp x16, :got:const_table_got
+; ISEL-ASM-ELF-NEXT: ldr x16, [x16, :got_lo12:const_table_got]
; ISEL-ASM-ELF-NEXT: add x16, x16, #8
; ISEL-ASM-ELF-NEXT: mov x17, x0
; ISEL-ASM-ELF-NEXT: movk x17, #1234, lsl #48
@@ -205,6 +197,60 @@ define void @store_signed_arg(ptr %dest, ptr %p) {
ret void
}
+;--- finalize-isel-elf-got.ll
+
+; RUN: llc < finalize-isel-elf-got.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \
+; RUN: FileCheck --check-prefixes=ISEL-ELF-GOT-MIR %s
+; RUN: llc < finalize-isel-elf-got.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
+; RUN: -verify-machineinstrs -global-isel-abort=1 -asm-verbose=0 | \
+; RUN: FileCheck --check-prefixes=ISEL-ELF-GOT-ASM %s
+
+ at const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+
+; Similar to finalize-isel.ll, but tests conversion of LOADgotAUTH to LOADgotPAC.
+; This requires module-level attribute, thus a separate sub-file.
+
+define void @store_signed_const_got(ptr %dest) {
+; ISEL-ELF-GOT-MIR-LABEL: name: store_signed_const_got
+; ISEL-ELF-GOT-MIR: body:
+; ISEL-ELF-GOT-MIR: %0:gpr64common = COPY $x0
+; ISEL-ELF-GOT-MIR-NEXT: %7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got
+; ISEL-ELF-GOT-MIR-NEXT: %6:gpr64common = ADDXri %7, 8, 0
+; ISEL-ELF-GOT-MIR-NEXT: %2:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-ELF-GOT-MIR-NEXT: %12:gpr64noip = COPY %0
+; ISEL-ELF-GOT-MIR-NEXT: LOADgotPAC target-flags(aarch64-got) @const_table_got + 8, 2, %12, 1234, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
+; ISEL-ELF-GOT-MIR-NEXT: %4:gpr64 = COPY $x16
+; ISEL-ELF-GOT-MIR-NEXT: %10:gpr64 = COPY %4
+; ISEL-ELF-GOT-MIR-NEXT: STRXui %10, %0, 0 :: (store (p0) into %ir.dest)
+; ISEL-ELF-GOT-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ELF-GOT-ASM-LABEL: store_signed_const_got:
+; ISEL-ELF-GOT-ASM-NEXT: .cfi_startproc
+; ISEL-ELF-GOT-ASM-NEXT: adrp x17, :got_auth:const_table_got
+; ISEL-ELF-GOT-ASM-NEXT: add x17, x17, :got_auth_lo12:const_table_got
+; ISEL-ELF-GOT-ASM-NEXT: ldr x16, [x17]
+; ISEL-ELF-GOT-ASM-NEXT: autda x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: mov x17, x16
+; ISEL-ELF-GOT-ASM-NEXT: xpacd x17
+; ISEL-ELF-GOT-ASM-NEXT: cmp x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: b.eq .Lauth_success_0
+; ISEL-ELF-GOT-ASM-NEXT: brk #0xc472
+; ISEL-ELF-GOT-ASM-NEXT: .Lauth_success_0:
+; ISEL-ELF-GOT-ASM-NEXT: add x16, x16, #8
+; ISEL-ELF-GOT-ASM-NEXT: mov x17, x0
+; ISEL-ELF-GOT-ASM-NEXT: movk x17, #1234, lsl #48
+; ISEL-ELF-GOT-ASM-NEXT: pacda x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: str x16, [x0]
+; ISEL-ELF-GOT-ASM-NEXT: ret
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
!llvm.module.flags = !{!0}
!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
index 84ce66b18fa51..217e1f96f04d5 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
@@ -125,7 +125,7 @@ define void @store_signed_const_got(ptr %dest) {
; ISEL-MIR-ELF: body:
; ISEL-MIR-ELF: %0:gpr64common = COPY $x0
; ISEL-MIR-ELF-NEXT: %1:gpr64noip = MOVKXi %0, 1234, 48
-; ISEL-MIR-ELF-NEXT: %2:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $nzcv
+; ISEL-MIR-ELF-NEXT: %2:gpr64common = LOADgot target-flags(aarch64-got) @const_table_got
; ISEL-MIR-ELF-NEXT: %3:gpr64common = ADDXri killed %2, 8, 0
; ISEL-MIR-ELF-NEXT: %5:gpr64noip = COPY %0
; ISEL-MIR-ELF-NEXT: LOADgotPAC target-flags(aarch64-got) @const_table_got + 8, 2, %5, 1234, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
@@ -135,16 +135,8 @@ define void @store_signed_const_got(ptr %dest) {
;
; ISEL-ASM-ELF-LABEL: store_signed_const_got:
; ISEL-ASM-ELF-NEXT: .cfi_startproc
-; ISEL-ASM-ELF-NEXT: adrp x17, :got_auth:const_table_got
-; ISEL-ASM-ELF-NEXT: add x17, x17, :got_auth_lo12:const_table_got
-; ISEL-ASM-ELF-NEXT: ldr x16, [x17]
-; ISEL-ASM-ELF-NEXT: autda x16, x17
-; ISEL-ASM-ELF-NEXT: mov x17, x16
-; ISEL-ASM-ELF-NEXT: xpacd x17
-; ISEL-ASM-ELF-NEXT: cmp x16, x17
-; ISEL-ASM-ELF-NEXT: b.eq .Lauth_success_0
-; ISEL-ASM-ELF-NEXT: brk #0xc472
-; ISEL-ASM-ELF-NEXT: .Lauth_success_0:
+; ISEL-ASM-ELF-NEXT: adrp x16, :got:const_table_got
+; ISEL-ASM-ELF-NEXT: ldr x16, [x16, :got_lo12:const_table_got]
; ISEL-ASM-ELF-NEXT: add x16, x16, #8
; ISEL-ASM-ELF-NEXT: mov x17, x0
; ISEL-ASM-ELF-NEXT: movk x17, #1234, lsl #48
@@ -189,6 +181,57 @@ define void @store_signed_arg(ptr %dest, ptr %p) {
ret void
}
+;--- finalize-isel-elf-got.ll
+
+; RUN: llc < finalize-isel-elf-got.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -stop-after=finalize-isel | FileCheck --check-prefixes=ISEL-ELF-GOT-MIR %s
+; RUN: llc < finalize-isel-elf-got.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
+; RUN: -verify-machineinstrs -asm-verbose=0 | FileCheck --check-prefixes=ISEL-ELF-GOT-ASM %s
+
+ at const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null]
+
+; Similar to finalize-isel.ll, but tests conversion of LOADgotAUTH to LOADgotPAC.
+; This requires module-level attribute, thus a separate sub-file.
+
+define void @store_signed_const_got(ptr %dest) {
+; ISEL-ELF-GOT-MIR-LABEL: name: store_signed_const_got
+; ISEL-ELF-GOT-MIR: body:
+; ISEL-ELF-GOT-MIR: %0:gpr64common = COPY $x0
+; ISEL-ELF-GOT-MIR-NEXT: %1:gpr64noip = MOVKXi %0, 1234, 48
+; ISEL-ELF-GOT-MIR-NEXT: %2:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $nzcv
+; ISEL-ELF-GOT-MIR-NEXT: %3:gpr64common = ADDXri killed %2, 8, 0
+; ISEL-ELF-GOT-MIR-NEXT: %5:gpr64noip = COPY %0
+; ISEL-ELF-GOT-MIR-NEXT: LOADgotPAC target-flags(aarch64-got) @const_table_got + 8, 2, %5, 1234, implicit-def $x16, implicit-def $x17, implicit-def $nzcv
+; ISEL-ELF-GOT-MIR-NEXT: %4:gpr64 = COPY $x16
+; ISEL-ELF-GOT-MIR-NEXT: STRXui killed %4, %0, 0 :: (store (s64) into %ir.dest)
+; ISEL-ELF-GOT-MIR-NEXT: RET_ReallyLR
+;
+; ISEL-ELF-GOT-ASM-LABEL: store_signed_const_got:
+; ISEL-ELF-GOT-ASM-NEXT: .cfi_startproc
+; ISEL-ELF-GOT-ASM-NEXT: adrp x17, :got_auth:const_table_got
+; ISEL-ELF-GOT-ASM-NEXT: add x17, x17, :got_auth_lo12:const_table_got
+; ISEL-ELF-GOT-ASM-NEXT: ldr x16, [x17]
+; ISEL-ELF-GOT-ASM-NEXT: autda x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: mov x17, x16
+; ISEL-ELF-GOT-ASM-NEXT: xpacd x17
+; ISEL-ELF-GOT-ASM-NEXT: cmp x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: b.eq .Lauth_success_0
+; ISEL-ELF-GOT-ASM-NEXT: brk #0xc472
+; ISEL-ELF-GOT-ASM-NEXT: .Lauth_success_0:
+; ISEL-ELF-GOT-ASM-NEXT: add x16, x16, #8
+; ISEL-ELF-GOT-ASM-NEXT: mov x17, x0
+; ISEL-ELF-GOT-ASM-NEXT: movk x17, #1234, lsl #48
+; ISEL-ELF-GOT-ASM-NEXT: pacda x16, x17
+; ISEL-ELF-GOT-ASM-NEXT: str x16, [x0]
+; ISEL-ELF-GOT-ASM-NEXT: ret
+ %dest.i = ptrtoint ptr %dest to i64
+ %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234)
+ %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr)
+ %signed.ptr = inttoptr i64 %signed.i to ptr
+ store ptr %signed.ptr, ptr %dest
+ ret void
+}
+
!llvm.module.flags = !{!0}
!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
More information about the llvm-branch-commits
mailing list