[AArch64][PAC] Select MOVK for ptrauth.blend intrinsic.

Blend combines two discriminator values used by other ptrauth ops.
On AArch64 here, it does that by replacing the high 16 bits of the
LHS with the low 16 bits of the RHS.

Usually the RHS is a constant, which lets us do this efficiently in
a single MOVK.  When the RHS isn't constant, we can do a BFI.

In a sense, this is implementing an ABI decision (how to lower the
software construct of "blend"), but if there are interesting variants to
consider, this could be made object-file-format-specific in some way.

Differential Revision: https://reviews.llvm.org/D132384
This commit is contained in:
Ahmed Bougacha
2022-10-24 08:33:30 -07:00
parent fb13d027ea
commit b3272f5ddb
4 changed files with 81 additions and 0 deletions

View File

@@ -889,6 +889,10 @@ def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
return ((uint64_t)Imm) < 65536;
}]>;
def imm64_0_65535 : Operand<i64>, ImmLeaf<i64, [{
return ((uint64_t)Imm) < 65536;
}]>;
}
def imm0_255 : Operand<i32>, ImmLeaf<i32, [{

View File

@@ -8849,6 +8849,18 @@ let Predicates = [HasMOPS, HasMTE], Defs = [NZCV], Size = 12, mayLoad = 0, maySt
[], "$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

View File

@@ -5976,6 +5976,25 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I,
I.eraseFromParent();
return true;
}
case Intrinsic::ptrauth_blend: {
MachineFunction &MF = *I.getParent()->getParent();
auto RHS = getIConstantVRegVal(I.getOperand(3).getReg(), MRI);
if (RHS && (RHS->getZExtValue() <= 0xffff)) {
I.setDesc(TII.get(AArch64::MOVKXi));
I.removeOperand(3);
I.removeOperand(1);
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();

View File

@@ -0,0 +1,46 @@
; 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
}
; Blends of constants wider than 16 bits truncate the constant.
define i64 @test_blend_constant_wide(i64 %arg) {
; CHECK-LABEL: test_blend_constant_wide:
; CHECK: ; %bb.0:
; CHECK-NEXT: mov w8, #65536
; CHECK-NEXT: bfi x0, x8, #48, #16
; CHECK-NEXT: ret
%tmp = call i64 @llvm.ptrauth.blend(i64 %arg, i64 65536)
ret i64 %tmp
}
declare i64 @llvm.ptrauth.blend(i64, i64)