https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/130809
>From dd48b1e499cae31f4d1ab2407a90c3fb68e04bea Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Thu, 10 Jul 2025 21:37:40 +0300 Subject: [PATCH 1/6] s/fixupBlendComponents/fixupPtrauthDiscriminator/ --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 6 +++--- llvm/lib/Target/AArch64/AArch64ISelLowering.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 8030184245298..ffa406b8a2f4c 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3105,7 +3105,7 @@ static MachineInstr *stripVRegCopies(const MachineRegisterInfo &MRI, return nullptr; } -void AArch64TargetLowering::fixupBlendComponents( +void AArch64TargetLowering::fixupPtrauthDiscriminator( MachineInstr &MI, MachineBasicBlock *BB, MachineOperand &IntDiscOp, MachineOperand &AddrDiscOp, const TargetRegisterClass *AddrDiscRC) const { const TargetInstrInfo *TII = Subtarget->getInstrInfo(); @@ -3249,8 +3249,8 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); case AArch64::PAC: - fixupBlendComponents(MI, BB, MI.getOperand(3), MI.getOperand(4), - &AArch64::GPR64noipRegClass); + fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4), + &AArch64::GPR64noipRegClass); return BB; } } diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index f3d4e99d3f77c..41c4560a1d453 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -184,10 +184,10 @@ class AArch64TargetLowering : public TargetLowering { /// Replace (0, vreg) discriminator components with the operands of blend /// or with (immediate, XZR) when possible. - void fixupBlendComponents(MachineInstr &MI, MachineBasicBlock *BB, - MachineOperand &IntDiscOp, - MachineOperand &AddrDiscOp, - const TargetRegisterClass *AddrDiscRC) const; + void fixupPtrauthDiscriminator(MachineInstr &MI, MachineBasicBlock *BB, + MachineOperand &IntDiscOp, + MachineOperand &AddrDiscOp, + const TargetRegisterClass *AddrDiscRC) const; MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, >From 382565b2343264355b8bd3012c28fe5d250b55de Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Sat, 28 Jun 2025 11:09:01 +0300 Subject: [PATCH 2/6] [AArch64][PAC] Rework discriminator analysis in AUT and AUTPAC Make use of post-processing the discriminator components by custom inserter hook to eliminate duplication for DAGISel and GlobalISel and improve cross-BB analysis for DAGISel. --- .../Target/AArch64/AArch64ISelDAGToDAG.cpp | 53 +--- .../Target/AArch64/AArch64ISelLowering.cpp | 10 + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 + .../GISel/AArch64InstructionSelector.cpp | 31 +-- llvm/test/CodeGen/AArch64/ptrauth-isel.ll | 235 +++++++++++++++++- 5 files changed, 259 insertions(+), 72 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index eca7ca566cfc2..475997f42ba82 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -1487,39 +1487,6 @@ void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); } -static std::tuple<SDValue, SDValue> -extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG) { - SDLoc DL(Disc); - SDValue AddrDisc; - SDValue ConstDisc; - - // If this is a blend, remember the constant and address discriminators. - // Otherwise, it's either a constant discriminator, or a non-blended - // address discriminator. - if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN && - Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) { - AddrDisc = Disc->getOperand(1); - ConstDisc = Disc->getOperand(2); - } else { - ConstDisc = Disc; - } - - // If the constant discriminator (either the blend RHS, or the entire - // discriminator value) isn't a 16-bit constant, bail out, and let the - // discriminator be computed separately. - auto *ConstDiscN = dyn_cast<ConstantSDNode>(ConstDisc); - if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue())) - return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc); - - // If there's no address discriminator, use XZR directly. - if (!AddrDisc) - AddrDisc = DAG->getRegister(AArch64::XZR, MVT::i64); - - return std::make_tuple( - DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64), - AddrDisc); -} - void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { SDLoc DL(N); // IntrinsicID is operand #0 @@ -1530,12 +1497,10 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { unsigned AUTKeyC = cast<ConstantSDNode>(AUTKey)->getZExtValue(); AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); if (!Subtarget->isX16X17Safer()) { - SDValue Ops[] = {Val, AUTKey, AUTConstDisc, AUTAddrDisc}; + SDValue Ops[] = {Val, AUTKey, Zero, AUTDisc}; SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTxMxN, DL, MVT::i64, MVT::i64, Ops); @@ -1543,7 +1508,7 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { } else { SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = {AUTKey, Zero, AUTDisc, X16Copy.getValue(1)}; SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17, DL, MVT::i64, Ops); ReplaceNode(N, AUT); @@ -1565,19 +1530,13 @@ void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) { AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); - - SDValue PACAddrDisc, PACConstDisc; - std::tie(PACConstDisc, PACAddrDisc) = - extractPtrauthBlendDiscriminators(PACDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey, - PACConstDisc, PACAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = { + AUTKey, Zero, AUTDisc, PACKey, Zero, PACDisc, X16Copy.getValue(1)}; SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops); ReplaceNode(N, AUTPAC); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index ffa406b8a2f4c..78e952a16e200 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3248,10 +3248,20 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( case AArch64::MOVT_TIZ_PSEUDO: return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); + case AArch64::AUT: + fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), + &AArch64::GPR64noipRegClass); + return BB; case AArch64::PAC: fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4), &AArch64::GPR64noipRegClass); return BB; + case AArch64::AUTPAC: + fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), + &AArch64::GPR64noipRegClass); + fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), + &AArch64::GPR64noipRegClass); + return BB; } } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index f637cc3343418..fe3de4f3c173f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2141,6 +2141,7 @@ let Predicates = [HasPAuth] in { let Size = 32; let Defs = [X16,X17,NZCV]; let Uses = [X16]; + let usesCustomInserter = 1; } def AUTxMxN : Pseudo<(outs GPR64:$AuthVal, GPR64common:$Scratch), @@ -2190,6 +2191,7 @@ let Predicates = [HasPAuth] in { let Size = 48; let Defs = [X16,X17,NZCV]; let Uses = [X16]; + let usesCustomInserter = 1; } // Materialize a signed global address, with adrp+add and PAC. diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 1381a9b70df87..2692685317f2f 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -6725,25 +6725,15 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, uint64_t PACKey = I.getOperand(5).getImm(); Register PACDisc = I.getOperand(6).getReg(); - Register AUTAddrDisc = AUTDisc; - uint16_t AUTConstDiscC = 0; - std::tie(AUTConstDiscC, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, MRI); - - Register PACAddrDisc = PACDisc; - uint16_t PACConstDiscC = 0; - std::tie(PACConstDiscC, PACAddrDisc) = - extractPtrauthBlendDiscriminators(PACDisc, MRI); - MIB.buildCopy({AArch64::X16}, {ValReg}); MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); MIB.buildInstr(AArch64::AUTPAC) .addImm(AUTKey) - .addImm(AUTConstDiscC) - .addUse(AUTAddrDisc) + .addImm(0) + .addUse(AUTDisc) .addImm(PACKey) - .addImm(PACConstDiscC) - .addUse(PACAddrDisc) + .addImm(0) + .addUse(PACDisc) .constrainAllUses(TII, TRI, RBI); MIB.buildCopy({DstReg}, Register(AArch64::X16)); @@ -6757,18 +6747,13 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, uint64_t AUTKey = I.getOperand(3).getImm(); Register AUTDisc = I.getOperand(4).getReg(); - Register AUTAddrDisc = AUTDisc; - uint16_t AUTConstDiscC = 0; - std::tie(AUTConstDiscC, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, MRI); - if (STI.isX16X17Safer()) { MIB.buildCopy({AArch64::X16}, {ValReg}); MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); MIB.buildInstr(AArch64::AUTx16x17) .addImm(AUTKey) - .addImm(AUTConstDiscC) - .addUse(AUTAddrDisc) + .addImm(0) + .addUse(AUTDisc) .constrainAllUses(TII, TRI, RBI); MIB.buildCopy({DstReg}, Register(AArch64::X16)); } else { @@ -6779,8 +6764,8 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, .addDef(ScratchReg) .addUse(ValReg) .addImm(AUTKey) - .addImm(AUTConstDiscC) - .addUse(AUTAddrDisc) + .addImm(0) + .addUse(AUTDisc) .constrainAllUses(TII, TRI, RBI); } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll index 1815d642aa5ed..f2e2195699daf 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll @@ -14,8 +14,8 @@ @discvar = dso_local global i64 0 ; Make sure the components of blend(addr, imm) are recognized and passed to -; PAC pseudo via separate operands to prevent substitution of the immediate -; modifier. +; AUT / PAC / AUTPAC pseudo via separate operands to prevent substitution of +; the immediate modifier. ; ; MIR output of the instruction selector is inspected, as it is hard to reliably ; distinguish MOVKXi immediately followed by a pseudo from a standalone pseudo @@ -101,6 +101,44 @@ entry: ret i64 %signed } +define i64 @blend_and_auth_same_bb(i64 %addr) { + ; DAGISEL-LABEL: name: blend_and_auth_same_bb + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: liveins: $x0 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-NEXT: $x16 = COPY [[COPY]] + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUT 2, 42, killed [[COPY1]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-NEXT: $x0 = COPY [[COPY2]] + ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-LABEL: name: blend_and_auth_same_bb + ; GISEL: bb.1.entry: + ; GISEL-NEXT: liveins: $x0 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: $x16 = COPY [[COPY]] + ; GISEL-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: AUT 2, 42, [[COPY1]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-NEXT: $x0 = COPY [[COPY2]] + ; GISEL-NEXT: RET_ReallyLR implicit $x0 +entry: + %addrdisc = load i64, ptr @discvar + %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + %authed = call i64 @llvm.ptrauth.auth(i64 %addr, i32 2, i64 %disc) + ret i64 %authed +} + define i64 @blend_and_sign_same_bb(i64 %addr) { ; DAGISEL-LABEL: name: blend_and_sign_same_bb ; DAGISEL: bb.0.entry: @@ -134,10 +172,124 @@ entry: ret i64 %signed } +define i64 @blend_and_resign_same_bb(i64 %addr) { + ; DAGISEL-LABEL: name: blend_and_resign_same_bb + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: liveins: $x0 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 123, 48 + ; DAGISEL-NEXT: $x16 = COPY [[COPY]] + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUTPAC 2, 42, killed [[COPY1]], 3, 123, killed [[COPY2]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-NEXT: $x0 = COPY [[COPY3]] + ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-LABEL: name: blend_and_resign_same_bb + ; GISEL: bb.1.entry: + ; GISEL-NEXT: liveins: $x0 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 123, 48 + ; GISEL-NEXT: $x16 = COPY [[COPY]] + ; GISEL-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: AUTPAC 2, 42, [[COPY1]], 3, 123, [[COPY2]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-NEXT: $x0 = COPY [[COPY3]] + ; GISEL-NEXT: RET_ReallyLR implicit $x0 +entry: + %addrdisc = load i64, ptr @discvar + %auth.disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + %sign.disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 123) + %resigned = call i64 @llvm.ptrauth.resign(i64 %addr, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc) + ret i64 %resigned +} + ; In the below test cases both %addrdisc and %disc are computed (i.e. they are ; neither global addresses, nor function arguments) in a different basic block, ; making them harder to express via ISD::PtrAuthGlobalAddress. +define i64 @blend_and_auth_different_bbs(i64 %addr, i64 %cond) { + ; DAGISEL-LABEL: name: blend_and_auth_different_bbs + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000) + ; DAGISEL-NEXT: liveins: $x0, $x1 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[MOVKXi]] + ; DAGISEL-NEXT: CBZX [[COPY]], %bb.2 + ; DAGISEL-NEXT: B %bb.1 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: bb.1.next: + ; DAGISEL-NEXT: successors: %bb.2(0x80000000) + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[COPY2]] + ; DAGISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY3]] + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: bb.2.exit: + ; DAGISEL-NEXT: $x16 = COPY [[COPY1]] + ; DAGISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUT 2, 42, [[COPY4]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-NEXT: [[COPY5:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-NEXT: $x0 = COPY [[COPY5]] + ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-LABEL: name: blend_and_auth_different_bbs + ; GISEL: bb.1.entry: + ; GISEL-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000) + ; GISEL-NEXT: liveins: $x0, $x1 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: CBZX [[COPY1]], %bb.3 + ; GISEL-NEXT: B %bb.2 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.2.next: + ; GISEL-NEXT: successors: %bb.3(0x80000000) + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]] + ; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]] + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.3.exit: + ; GISEL-NEXT: $x16 = COPY [[COPY]] + ; GISEL-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: AUT 2, 42, [[COPY3]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-NEXT: $x0 = COPY [[COPY4]] + ; GISEL-NEXT: RET_ReallyLR implicit $x0 +entry: + %addrdisc = load i64, ptr @discvar + %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + %cond.b = icmp ne i64 %cond, 0 + br i1 %cond.b, label %next, label %exit + +next: + call void asm sideeffect "nop", "r"(i64 %disc) + br label %exit + +exit: + %authed = call i64 @llvm.ptrauth.auth(i64 %addr, i32 2, i64 %disc) + ret i64 %authed +} + define i64 @blend_and_sign_different_bbs(i64 %addr, i64 %cond) { ; DAGISEL-LABEL: name: blend_and_sign_different_bbs ; DAGISEL: bb.0.entry: @@ -203,3 +355,82 @@ exit: %signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 %disc) ret i64 %signed } + +define i64 @blend_and_resign_different_bbs(i64 %addr, i64 %cond) { + ; DAGISEL-LABEL: name: blend_and_resign_different_bbs + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000) + ; DAGISEL-NEXT: liveins: $x0, $x1 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[MOVKXi]] + ; DAGISEL-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 123, 48 + ; DAGISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[MOVKXi1]] + ; DAGISEL-NEXT: CBZX [[COPY]], %bb.2 + ; DAGISEL-NEXT: B %bb.1 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: bb.1.next: + ; DAGISEL-NEXT: successors: %bb.2(0x80000000) + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64common = COPY [[COPY2]] + ; DAGISEL-NEXT: [[COPY5:%[0-9]+]]:gpr64common = COPY [[COPY3]] + ; DAGISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY4]], 3866633 /* reguse:GPR64common */, [[COPY5]] + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: bb.2.exit: + ; DAGISEL-NEXT: $x16 = COPY [[COPY1]] + ; DAGISEL-NEXT: [[COPY6:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: [[COPY7:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUTPAC 2, 42, [[COPY6]], 3, 123, [[COPY7]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-NEXT: [[COPY8:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-NEXT: $x0 = COPY [[COPY8]] + ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-LABEL: name: blend_and_resign_different_bbs + ; GISEL: bb.1.entry: + ; GISEL-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000) + ; GISEL-NEXT: liveins: $x0, $x1 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 123, 48 + ; GISEL-NEXT: CBZX [[COPY1]], %bb.3 + ; GISEL-NEXT: B %bb.2 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.2.next: + ; GISEL-NEXT: successors: %bb.3(0x80000000) + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]] + ; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[MOVKXi1]] + ; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]], 3866633 /* reguse:GPR64common */, [[COPY3]] + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.3.exit: + ; GISEL-NEXT: $x16 = COPY [[COPY]] + ; GISEL-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: [[COPY5:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: AUTPAC 2, 42, [[COPY4]], 3, 123, [[COPY5]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-NEXT: [[COPY6:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-NEXT: $x0 = COPY [[COPY6]] + ; GISEL-NEXT: RET_ReallyLR implicit $x0 +entry: + %addrdisc = load i64, ptr @discvar + %auth.disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + %sign.disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 123) + %cond.b = icmp ne i64 %cond, 0 + br i1 %cond.b, label %next, label %exit + +next: + call void asm sideeffect "nop", "r,r"(i64 %auth.disc, i64 %sign.disc) + br label %exit + +exit: + %resigned = call i64 @llvm.ptrauth.resign(i64 %addr, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc) + ret i64 %resigned +} >From 20392f7a85038e7f728dd8b9f281550326121dd1 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Thu, 10 Jul 2025 16:04:43 +0300 Subject: [PATCH 3/6] Update tests --- .../Target/AArch64/AArch64ISelLowering.cpp | 6 +- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 1 + llvm/test/CodeGen/AArch64/ptrauth-isel.ll | 251 ++++++++++++------ 3 files changed, 170 insertions(+), 88 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 78e952a16e200..d1af641b344fb 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3248,10 +3248,14 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( case AArch64::MOVT_TIZ_PSEUDO: return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); - case AArch64::AUT: + case AArch64::AUTx16x17: fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), &AArch64::GPR64noipRegClass); return BB; + case AArch64::AUTxMxN: + fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), + &AArch64::GPR64noipRegClass); + return BB; case AArch64::PAC: fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4), &AArch64::GPR64noipRegClass); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index fe3de4f3c173f..35d96168a1518 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2155,6 +2155,7 @@ let Predicates = [HasPAuth] in { let Size = 32; let Defs = [NZCV]; let Uses = []; + let usesCustomInserter = 1; } // PAC pseudo instruction. Is AsmPrinter, it is expanded into an actual PAC* diff --git a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll index f2e2195699daf..2ce8732005aa6 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll @@ -1,12 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 ; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \ -; RUN: | FileCheck %s --check-prefixes=DAGISEL +; RUN: | FileCheck %s --check-prefixes=DAGISEL,DAGISEL-DARWIN ; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \ -; RUN: | FileCheck %s --check-prefixes=GISEL +; RUN: | FileCheck %s --check-prefixes=GISEL,GISEL-DARWIN ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \ -; RUN: | FileCheck %s --check-prefixes=DAGISEL +; RUN: | FileCheck %s --check-prefixes=DAGISEL,DAGISEL-ELF ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \ -; RUN: | FileCheck %s --check-prefixes=GISEL +; RUN: | FileCheck %s --check-prefixes=GISEL,GISEL-ELF ; Check MIR produced by the instruction selector to validate properties that ; cannot be reliably tested by only inspecting the final asm output. @@ -102,36 +102,62 @@ entry: } define i64 @blend_and_auth_same_bb(i64 %addr) { - ; DAGISEL-LABEL: name: blend_and_auth_same_bb - ; DAGISEL: bb.0.entry: - ; DAGISEL-NEXT: liveins: $x0 - ; DAGISEL-NEXT: {{ $}} - ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar - ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) - ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 - ; DAGISEL-NEXT: $x16 = COPY [[COPY]] - ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] - ; DAGISEL-NEXT: AUT 2, 42, killed [[COPY1]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 - ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64all = COPY $x16 - ; DAGISEL-NEXT: $x0 = COPY [[COPY2]] - ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; DAGISEL-DARWIN-LABEL: name: blend_and_auth_same_bb + ; DAGISEL-DARWIN: bb.0.entry: + ; DAGISEL-DARWIN-NEXT: liveins: $x0 + ; DAGISEL-DARWIN-NEXT: {{ $}} + ; DAGISEL-DARWIN-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-DARWIN-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-DARWIN-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-DARWIN-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-DARWIN-NEXT: $x16 = COPY [[COPY]] + ; DAGISEL-DARWIN-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-DARWIN-NEXT: AUTx16x17 2, 42, killed [[COPY1]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-DARWIN-NEXT: [[COPY2:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-DARWIN-NEXT: $x0 = COPY [[COPY2]] + ; DAGISEL-DARWIN-NEXT: RET_ReallyLR implicit $x0 ; - ; GISEL-LABEL: name: blend_and_auth_same_bb - ; GISEL: bb.1.entry: - ; GISEL-NEXT: liveins: $x0 - ; GISEL-NEXT: {{ $}} - ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 - ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar - ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) - ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 - ; GISEL-NEXT: $x16 = COPY [[COPY]] - ; GISEL-NEXT: $x17 = IMPLICIT_DEF - ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] - ; GISEL-NEXT: AUT 2, 42, [[COPY1]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 - ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x16 - ; GISEL-NEXT: $x0 = COPY [[COPY2]] - ; GISEL-NEXT: RET_ReallyLR implicit $x0 + ; GISEL-DARWIN-LABEL: name: blend_and_auth_same_bb + ; GISEL-DARWIN: bb.1.entry: + ; GISEL-DARWIN-NEXT: liveins: $x0 + ; GISEL-DARWIN-NEXT: {{ $}} + ; GISEL-DARWIN-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-DARWIN-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-DARWIN-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-DARWIN-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-DARWIN-NEXT: $x16 = COPY [[COPY]] + ; GISEL-DARWIN-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-DARWIN-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-DARWIN-NEXT: AUTx16x17 2, 42, [[COPY1]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-DARWIN-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-DARWIN-NEXT: $x0 = COPY [[COPY2]] + ; GISEL-DARWIN-NEXT: RET_ReallyLR implicit $x0 + ; + ; DAGISEL-ELF-LABEL: name: blend_and_auth_same_bb + ; DAGISEL-ELF: bb.0.entry: + ; DAGISEL-ELF-NEXT: liveins: $x0 + ; DAGISEL-ELF-NEXT: {{ $}} + ; DAGISEL-ELF-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-ELF-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-ELF-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-ELF-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-ELF-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-ELF-NEXT: [[AUTxMxN:%[0-9]+]]:gpr64, [[AUTxMxN1:%[0-9]+]]:gpr64common = AUTxMxN [[COPY]], 2, 42, killed [[COPY1]], implicit-def dead $nzcv + ; DAGISEL-ELF-NEXT: $x0 = COPY [[AUTxMxN]] + ; DAGISEL-ELF-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-ELF-LABEL: name: blend_and_auth_same_bb + ; GISEL-ELF: bb.1.entry: + ; GISEL-ELF-NEXT: liveins: $x0 + ; GISEL-ELF-NEXT: {{ $}} + ; GISEL-ELF-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; GISEL-ELF-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-ELF-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-ELF-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-ELF-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-ELF-NEXT: [[AUTxMxN:%[0-9]+]]:gpr64, [[AUTxMxN1:%[0-9]+]]:gpr64common = AUTxMxN [[COPY]], 2, 42, [[COPY1]], implicit-def dead $nzcv + ; GISEL-ELF-NEXT: $x0 = COPY [[AUTxMxN]] + ; GISEL-ELF-NEXT: RET_ReallyLR implicit $x0 entry: %addrdisc = load i64, ptr @discvar %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) @@ -220,61 +246,112 @@ entry: ; making them harder to express via ISD::PtrAuthGlobalAddress. define i64 @blend_and_auth_different_bbs(i64 %addr, i64 %cond) { - ; DAGISEL-LABEL: name: blend_and_auth_different_bbs - ; DAGISEL: bb.0.entry: - ; DAGISEL-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000) - ; DAGISEL-NEXT: liveins: $x0, $x1 - ; DAGISEL-NEXT: {{ $}} - ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 - ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 - ; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar - ; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) - ; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 - ; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[MOVKXi]] - ; DAGISEL-NEXT: CBZX [[COPY]], %bb.2 - ; DAGISEL-NEXT: B %bb.1 - ; DAGISEL-NEXT: {{ $}} - ; DAGISEL-NEXT: bb.1.next: - ; DAGISEL-NEXT: successors: %bb.2(0x80000000) - ; DAGISEL-NEXT: {{ $}} - ; DAGISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[COPY2]] - ; DAGISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY3]] - ; DAGISEL-NEXT: {{ $}} - ; DAGISEL-NEXT: bb.2.exit: - ; DAGISEL-NEXT: $x16 = COPY [[COPY1]] - ; DAGISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] - ; DAGISEL-NEXT: AUT 2, 42, [[COPY4]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 - ; DAGISEL-NEXT: [[COPY5:%[0-9]+]]:gpr64all = COPY $x16 - ; DAGISEL-NEXT: $x0 = COPY [[COPY5]] - ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; DAGISEL-DARWIN-LABEL: name: blend_and_auth_different_bbs + ; DAGISEL-DARWIN: bb.0.entry: + ; DAGISEL-DARWIN-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000) + ; DAGISEL-DARWIN-NEXT: liveins: $x0, $x1 + ; DAGISEL-DARWIN-NEXT: {{ $}} + ; DAGISEL-DARWIN-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; DAGISEL-DARWIN-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-DARWIN-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-DARWIN-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-DARWIN-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-DARWIN-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[MOVKXi]] + ; DAGISEL-DARWIN-NEXT: CBZX [[COPY]], %bb.2 + ; DAGISEL-DARWIN-NEXT: B %bb.1 + ; DAGISEL-DARWIN-NEXT: {{ $}} + ; DAGISEL-DARWIN-NEXT: bb.1.next: + ; DAGISEL-DARWIN-NEXT: successors: %bb.2(0x80000000) + ; DAGISEL-DARWIN-NEXT: {{ $}} + ; DAGISEL-DARWIN-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[COPY2]] + ; DAGISEL-DARWIN-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY3]] + ; DAGISEL-DARWIN-NEXT: {{ $}} + ; DAGISEL-DARWIN-NEXT: bb.2.exit: + ; DAGISEL-DARWIN-NEXT: $x16 = COPY [[COPY1]] + ; DAGISEL-DARWIN-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-DARWIN-NEXT: AUTx16x17 2, 42, [[COPY4]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16 + ; DAGISEL-DARWIN-NEXT: [[COPY5:%[0-9]+]]:gpr64all = COPY $x16 + ; DAGISEL-DARWIN-NEXT: $x0 = COPY [[COPY5]] + ; DAGISEL-DARWIN-NEXT: RET_ReallyLR implicit $x0 ; - ; GISEL-LABEL: name: blend_and_auth_different_bbs - ; GISEL: bb.1.entry: - ; GISEL-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000) - ; GISEL-NEXT: liveins: $x0, $x1 - ; GISEL-NEXT: {{ $}} - ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 - ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar - ; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) - ; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 - ; GISEL-NEXT: CBZX [[COPY1]], %bb.3 - ; GISEL-NEXT: B %bb.2 - ; GISEL-NEXT: {{ $}} - ; GISEL-NEXT: bb.2.next: - ; GISEL-NEXT: successors: %bb.3(0x80000000) - ; GISEL-NEXT: {{ $}} - ; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]] - ; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]] - ; GISEL-NEXT: {{ $}} - ; GISEL-NEXT: bb.3.exit: - ; GISEL-NEXT: $x16 = COPY [[COPY]] - ; GISEL-NEXT: $x17 = IMPLICIT_DEF - ; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] - ; GISEL-NEXT: AUT 2, 42, [[COPY3]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 - ; GISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64 = COPY $x16 - ; GISEL-NEXT: $x0 = COPY [[COPY4]] - ; GISEL-NEXT: RET_ReallyLR implicit $x0 + ; GISEL-DARWIN-LABEL: name: blend_and_auth_different_bbs + ; GISEL-DARWIN: bb.1.entry: + ; GISEL-DARWIN-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000) + ; GISEL-DARWIN-NEXT: liveins: $x0, $x1 + ; GISEL-DARWIN-NEXT: {{ $}} + ; GISEL-DARWIN-NEXT: [[COPY:%[0-9]+]]:gpr64all = COPY $x0 + ; GISEL-DARWIN-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; GISEL-DARWIN-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-DARWIN-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-DARWIN-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-DARWIN-NEXT: CBZX [[COPY1]], %bb.3 + ; GISEL-DARWIN-NEXT: B %bb.2 + ; GISEL-DARWIN-NEXT: {{ $}} + ; GISEL-DARWIN-NEXT: bb.2.next: + ; GISEL-DARWIN-NEXT: successors: %bb.3(0x80000000) + ; GISEL-DARWIN-NEXT: {{ $}} + ; GISEL-DARWIN-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]] + ; GISEL-DARWIN-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]] + ; GISEL-DARWIN-NEXT: {{ $}} + ; GISEL-DARWIN-NEXT: bb.3.exit: + ; GISEL-DARWIN-NEXT: $x16 = COPY [[COPY]] + ; GISEL-DARWIN-NEXT: $x17 = IMPLICIT_DEF + ; GISEL-DARWIN-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-DARWIN-NEXT: AUTx16x17 2, 42, [[COPY3]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16 + ; GISEL-DARWIN-NEXT: [[COPY4:%[0-9]+]]:gpr64 = COPY $x16 + ; GISEL-DARWIN-NEXT: $x0 = COPY [[COPY4]] + ; GISEL-DARWIN-NEXT: RET_ReallyLR implicit $x0 + ; + ; DAGISEL-ELF-LABEL: name: blend_and_auth_different_bbs + ; DAGISEL-ELF: bb.0.entry: + ; DAGISEL-ELF-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000) + ; DAGISEL-ELF-NEXT: liveins: $x0, $x1 + ; DAGISEL-ELF-NEXT: {{ $}} + ; DAGISEL-ELF-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; DAGISEL-ELF-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 + ; DAGISEL-ELF-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; DAGISEL-ELF-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; DAGISEL-ELF-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; DAGISEL-ELF-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[MOVKXi]] + ; DAGISEL-ELF-NEXT: CBZX [[COPY]], %bb.2 + ; DAGISEL-ELF-NEXT: B %bb.1 + ; DAGISEL-ELF-NEXT: {{ $}} + ; DAGISEL-ELF-NEXT: bb.1.next: + ; DAGISEL-ELF-NEXT: successors: %bb.2(0x80000000) + ; DAGISEL-ELF-NEXT: {{ $}} + ; DAGISEL-ELF-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[COPY2]] + ; DAGISEL-ELF-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY3]] + ; DAGISEL-ELF-NEXT: {{ $}} + ; DAGISEL-ELF-NEXT: bb.2.exit: + ; DAGISEL-ELF-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-ELF-NEXT: [[AUTxMxN:%[0-9]+]]:gpr64, [[AUTxMxN1:%[0-9]+]]:gpr64common = AUTxMxN [[COPY1]], 2, 42, [[COPY4]], implicit-def dead $nzcv + ; DAGISEL-ELF-NEXT: $x0 = COPY [[AUTxMxN]] + ; DAGISEL-ELF-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-ELF-LABEL: name: blend_and_auth_different_bbs + ; GISEL-ELF: bb.1.entry: + ; GISEL-ELF-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000) + ; GISEL-ELF-NEXT: liveins: $x0, $x1 + ; GISEL-ELF-NEXT: {{ $}} + ; GISEL-ELF-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; GISEL-ELF-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; GISEL-ELF-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar + ; GISEL-ELF-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar) + ; GISEL-ELF-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-ELF-NEXT: CBZX [[COPY1]], %bb.3 + ; GISEL-ELF-NEXT: B %bb.2 + ; GISEL-ELF-NEXT: {{ $}} + ; GISEL-ELF-NEXT: bb.2.next: + ; GISEL-ELF-NEXT: successors: %bb.3(0x80000000) + ; GISEL-ELF-NEXT: {{ $}} + ; GISEL-ELF-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]] + ; GISEL-ELF-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]] + ; GISEL-ELF-NEXT: {{ $}} + ; GISEL-ELF-NEXT: bb.3.exit: + ; GISEL-ELF-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-ELF-NEXT: [[AUTxMxN:%[0-9]+]]:gpr64, [[AUTxMxN1:%[0-9]+]]:gpr64common = AUTxMxN [[COPY]], 2, 42, [[COPY3]], implicit-def dead $nzcv + ; GISEL-ELF-NEXT: $x0 = COPY [[AUTxMxN]] + ; GISEL-ELF-NEXT: RET_ReallyLR implicit $x0 entry: %addrdisc = load i64, ptr @discvar %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) >From 580b8bfdab1ae49919259b74ffc843274e0da843 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Thu, 10 Jul 2025 21:39:24 +0300 Subject: [PATCH 4/6] s/fixupBlendComponents/fixupPtrauthDiscriminator/ --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index d1af641b344fb..53491c4284e05 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3249,22 +3249,22 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); case AArch64::AUTx16x17: - fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), - &AArch64::GPR64noipRegClass); + fixupPtrauthDiscriminator(MI, BB, MI.getOperand(1), MI.getOperand(2), + &AArch64::GPR64noipRegClass); return BB; case AArch64::AUTxMxN: - fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), - &AArch64::GPR64noipRegClass); + fixupPtrauthDiscriminator(MI, BB, MI.getOperand(4), MI.getOperand(5), + &AArch64::GPR64noipRegClass); return BB; case AArch64::PAC: fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4), &AArch64::GPR64noipRegClass); return BB; case AArch64::AUTPAC: - fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), - &AArch64::GPR64noipRegClass); - fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), - &AArch64::GPR64noipRegClass); + fixupPtrauthDiscriminator(MI, BB, MI.getOperand(1), MI.getOperand(2), + &AArch64::GPR64noipRegClass); + fixupPtrauthDiscriminator(MI, BB, MI.getOperand(4), MI.getOperand(5), + &AArch64::GPR64noipRegClass); return BB; } } >From a79704c1d7c4e61846b0f086112bd45381e42df7 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Mon, 10 Mar 2025 15:14:55 +0300 Subject: [PATCH 5/6] [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..140e29f942a79 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 + +@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] + +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 $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 $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 $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..429ff6e5489aa 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 + +@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] + +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 $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 $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 $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 b4a24f05f8772928580d517649eea5890e65829d Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko <atrosine...@accesssoftek.com> Date: Mon, 30 Jun 2025 19:19:13 +0300 Subject: [PATCH 6/6] [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 | 78 +++++++++-- 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, 251 insertions(+), 77 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 53491c4284e05..2283d6b3f5698 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3079,10 +3079,12 @@ 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 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 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"); @@ -3100,7 +3102,17 @@ static 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; } @@ -3117,9 +3129,13 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator( assert(IntDisc == 0 && "Blend components are already expanded"); - MachineInstr *MaybeBlend = stripVRegCopies(MRI, AddrDisc); + int64_t Offset = 0; + MachineInstr *MaybeBlend = stripAndAccumulateOffset(MRI, AddrDisc, Offset); - if (MaybeBlend) { + // 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 (MaybeBlend && Offset == 0) { // Detect blend(addr, imm) which is lowered as "MOVK addr, #imm, #48". // Alternatively, recognize small immediate modifier passed via VReg. if (MaybeBlend->getOpcode() == AArch64::MOVKXi && @@ -3149,6 +3165,52 @@ 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; + 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. + + 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 { @@ -3259,7 +3321,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 41c4560a1d453..74ea9f1c3df91 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 35d96168a1518..08c0122bf056e 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2220,6 +2220,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 140e29f942a79..b2081a2bea713 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 $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@PAGE +; ISEL-ASM-MACHO-NEXT: add x16, x16, _const_table_local@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 $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 $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 $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 x17, x0 +; ISEL-ASM-NEXT: movk x17, #1234, lsl #48 +; ISEL-ASM-NEXT: pacda x8, x17 +; 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 429ff6e5489aa..37f6ff1ec0818 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 $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@PAGE +; ISEL-ASM-MACHO-NEXT: add x16, x16, _const_table_local@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 $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 $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 $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 x17, x0 +; ISEL-ASM-NEXT: movk x17, #1234, lsl #48 +; ISEL-ASM-NEXT: pacda x8, x17 +; 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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits