Index: llvm/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -861,6 +861,10 @@ def timm64_0_65535 : Operand, TImmLeaf; + +def imm64_0_65535 : Operand, ImmLeaf; } // imm0_255 predicate - True if the immediate is in the range [0,255]. Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -8403,6 +8403,18 @@ [], "$Rd = $Rd_wb,$Rn = $Rn_wb">, Sched<[]>; } +//----------------------------------------------------------------------------- +// v8.3 Pointer Authentication late patterns + +let Predicates = [HasPAuth] in { +def : Pat<(int_ptrauth_blend GPR64:$Rd, imm64_0_65535:$imm), + (MOVKXi GPR64:$Rd, (trunc_imm imm64_0_65535:$imm), 48)>; +def : Pat<(int_ptrauth_blend GPR64:$Rd, GPR64:$Rn), + (BFMXri GPR64:$Rd, GPR64:$Rn, 16, 15)>; +} + +//----------------------------------------------------------------------------- + // This gets lowered into an instruction sequence of 20 bytes let Defs = [X16, X17], mayStore = 1, isCodeGenOnly = 1, Size = 20 in def StoreSwiftAsyncContext Index: llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -5867,6 +5867,25 @@ I.eraseFromParent(); return true; } + case Intrinsic::ptrauth_blend: { + MachineFunction &MF = *I.getParent()->getParent(); + auto RHS = getIConstantVRegVal(I.getOperand(3).getReg(), MRI); + if (RHS) { + I.setDesc(TII.get(AArch64::MOVKXi)); + I.removeOperand(1); + I.removeOperand(2); + MachineInstrBuilder(MF, I) + .addImm(RHS->getZExtValue() & 0xffff) + .addImm(48) + .constrainAllUses(TII, TRI, RBI); + } else { + I.setDesc(TII.get(AArch64::BFMXri)); + I.removeOperand(1); + MachineInstrBuilder(MF, I).addImm(16).addImm(15).constrainAllUses( + TII, TRI, RBI); + } + return true; + } case Intrinsic::frameaddress: case Intrinsic::returnaddress: { MachineFunction &MF = *I.getParent()->getParent(); Index: llvm/test/CodeGen/AArch64/ptrauth-intrinsic-blend.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/ptrauth-intrinsic-blend.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -global-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %s + +define i64 @test_blend(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_blend: +; CHECK: ; %bb.0: +; CHECK-NEXT: bfi x0, x1, #48, #16 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.ptrauth.blend(i64 %arg, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_blend_constant(i64 %arg) { +; CHECK-LABEL: test_blend_constant: +; CHECK: ; %bb.0: +; CHECK-NEXT: movk x0, #12345, lsl #48 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.ptrauth.blend(i64 %arg, i64 12345) + ret i64 %tmp +} + +; Blend isn't commutative. +define i64 @test_blend_constant_swapped(i64 %arg) { +; CHECK-LABEL: test_blend_constant_swapped: +; CHECK: ; %bb.0: +; CHECK-NEXT: mov w8, #12345 +; CHECK-NEXT: bfi x8, x0, #48, #16 +; CHECK-NEXT: mov x0, x8 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.ptrauth.blend(i64 12345, i64 %arg) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.blend(i64, i64)