Skip to content

Commit 614e4dd

Browse files
committed
146488
1 parent f3a8aab commit 614e4dd

File tree

5 files changed

+339
-1
lines changed

5 files changed

+339
-1
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ class AArch64AsmPrinter : public AsmPrinter {
184184
// defined in the current module so this function emitted a NOP instead.
185185
bool emitDeactivationSymbolRelocation(Value *DS);
186186

187+
// Emit the sequence for PAC.
188+
void emitPtrauthSign(const MachineInstr *MI);
189+
187190
// Emit the sequence to compute the discriminator.
188191
//
189192
// The returned register is either unmodified AddrDisc or ScratchReg.
@@ -2208,6 +2211,31 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(
22082211
OutStreamer->emitLabel(EndSym);
22092212
}
22102213

2214+
void AArch64AsmPrinter::emitPtrauthSign(const MachineInstr *MI) {
2215+
Register Val = MI->getOperand(1).getReg();
2216+
auto Key = (AArch64PACKey::ID)MI->getOperand(2).getImm();
2217+
uint64_t Disc = MI->getOperand(3).getImm();
2218+
Register AddrDisc = MI->getOperand(4).getReg();
2219+
bool AddrDiscKilled = MI->getOperand(4).isKill();
2220+
2221+
// Compute aut discriminator into x17
2222+
assert(isUInt<16>(Disc));
2223+
Register DiscReg = emitPtrauthDiscriminator(
2224+
Disc, AddrDisc, AArch64::X17, /*MayUseAddrAsScratch=*/AddrDiscKilled);
2225+
bool IsZeroDisc = DiscReg == AArch64::XZR;
2226+
unsigned Opc = getPACOpcodeForKey(Key, IsZeroDisc);
2227+
2228+
// paciza x16 ; if IsZeroDisc
2229+
// pacia x16, x17 ; if !IsZeroDisc
2230+
MCInst PACInst;
2231+
PACInst.setOpcode(Opc);
2232+
PACInst.addOperand(MCOperand::createReg(Val));
2233+
PACInst.addOperand(MCOperand::createReg(Val));
2234+
if (!IsZeroDisc)
2235+
PACInst.addOperand(MCOperand::createReg(DiscReg));
2236+
EmitToStreamer(*OutStreamer, PACInst);
2237+
}
2238+
22112239
void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
22122240
bool IsCall = MI->getOpcode() == AArch64::BLRA;
22132241
unsigned BrTarget = MI->getOperand(0).getReg();
@@ -3096,6 +3124,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
30963124
MI->getDeactivationSymbol());
30973125
return;
30983126

3127+
case AArch64::PAC:
3128+
emitPtrauthSign(MI);
3129+
return;
3130+
30993131
case AArch64::LOADauthptrstatic:
31003132
LowerLOADauthptrstatic(*MI);
31013133
return;

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,76 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
30793079
return BB;
30803080
}
30813081

3082+
// Helper function to find the instruction that defined a virtual register.
3083+
// If unable to find such instruction, returns nullptr.
3084+
static MachineInstr *stripVRegCopies(const MachineRegisterInfo &MRI,
3085+
Register Reg) {
3086+
while (Reg.isVirtual()) {
3087+
MachineInstr *DefMI = MRI.getVRegDef(Reg);
3088+
assert(DefMI && "Virtual register definition not found");
3089+
unsigned Opcode = DefMI->getOpcode();
3090+
3091+
if (Opcode == AArch64::COPY) {
3092+
Reg = DefMI->getOperand(1).getReg();
3093+
// Vreg is defined by copying from physreg.
3094+
if (Reg.isPhysical())
3095+
return DefMI;
3096+
continue;
3097+
}
3098+
if (Opcode == AArch64::SUBREG_TO_REG) {
3099+
Reg = DefMI->getOperand(2).getReg();
3100+
continue;
3101+
}
3102+
3103+
return DefMI;
3104+
}
3105+
return nullptr;
3106+
}
3107+
3108+
void AArch64TargetLowering::fixupPtrauthDiscriminator(
3109+
MachineInstr &MI, MachineBasicBlock *BB, MachineOperand &IntDiscOp,
3110+
MachineOperand &AddrDiscOp, const TargetRegisterClass *AddrDiscRC) const {
3111+
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3112+
MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3113+
const DebugLoc &DL = MI.getDebugLoc();
3114+
3115+
Register AddrDisc = AddrDiscOp.getReg();
3116+
int64_t IntDisc = IntDiscOp.getImm();
3117+
3118+
assert(IntDisc == 0 && "Blend components are already expanded");
3119+
3120+
MachineInstr *MaybeBlend = stripVRegCopies(MRI, AddrDisc);
3121+
3122+
if (MaybeBlend) {
3123+
// Detect blend(addr, imm) which is lowered as "MOVK addr, #imm, #48".
3124+
// Alternatively, recognize small immediate modifier passed via VReg.
3125+
if (MaybeBlend->getOpcode() == AArch64::MOVKXi &&
3126+
MaybeBlend->getOperand(3).getImm() == 48) {
3127+
AddrDisc = MaybeBlend->getOperand(1).getReg();
3128+
IntDisc = MaybeBlend->getOperand(2).getImm();
3129+
} else if (MaybeBlend->getOpcode() == AArch64::MOVi32imm &&
3130+
isUInt<16>(MaybeBlend->getOperand(1).getImm())) {
3131+
AddrDisc = AArch64::NoRegister;
3132+
IntDisc = MaybeBlend->getOperand(1).getImm();
3133+
}
3134+
}
3135+
3136+
// For uniformity, always use NoRegister, as XZR is not necessarily contained
3137+
// in the requested register class.
3138+
if (AddrDisc == AArch64::XZR)
3139+
AddrDisc = AArch64::NoRegister;
3140+
3141+
// Make sure AddrDisc operand respects the register class imposed by MI.
3142+
if (AddrDisc && MRI.getRegClass(AddrDisc) != AddrDiscRC) {
3143+
Register TmpReg = MRI.createVirtualRegister(AddrDiscRC);
3144+
BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc);
3145+
AddrDisc = TmpReg;
3146+
}
3147+
3148+
AddrDiscOp.setReg(AddrDisc);
3149+
IntDiscOp.setImm(IntDisc);
3150+
}
3151+
30823152
MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
30833153
MachineInstr &MI, MachineBasicBlock *BB) const {
30843154

@@ -3177,6 +3247,11 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
31773247
return EmitZTInstr(MI, BB, AArch64::ZERO_T, /*Op0IsDef=*/true);
31783248
case AArch64::MOVT_TIZ_PSEUDO:
31793249
return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true);
3250+
3251+
case AArch64::PAC:
3252+
fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4),
3253+
&AArch64::GPR64noipRegClass);
3254+
return BB;
31803255
}
31813256
}
31823257

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ class AArch64TargetLowering : public TargetLowering {
182182
MachineBasicBlock *EmitGetSMESaveSize(MachineInstr &MI,
183183
MachineBasicBlock *BB) const;
184184

185+
/// Replace (0, vreg) discriminator components with the operands of blend
186+
/// or with (immediate, XZR) when possible.
187+
void fixupPtrauthDiscriminator(MachineInstr &MI, MachineBasicBlock *BB,
188+
MachineOperand &IntDiscOp,
189+
MachineOperand &AddrDiscOp,
190+
const TargetRegisterClass *AddrDiscRC) const;
191+
185192
MachineBasicBlock *
186193
EmitInstrWithCustomInserter(MachineInstr &MI,
187194
MachineBasicBlock *MBB) const override;

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,7 @@ let Predicates = [HasPAuth] in {
20362036
def DZB : SignAuthZero<prefix_z, 0b11, !strconcat(asm, "dzb"), op>;
20372037
}
20382038

2039-
defm PAC : SignAuth<0b000, 0b010, "pac", int_ptrauth_sign>;
2039+
defm PAC : SignAuth<0b000, 0b010, "pac", null_frag>;
20402040
defm AUT : SignAuth<0b001, 0b011, "aut", null_frag>;
20412041

20422042
def XPACI : ClearAuth<0, "xpaci">;
@@ -2156,6 +2156,25 @@ let Predicates = [HasPAuth] in {
21562156
let Uses = [];
21572157
}
21582158

2159+
// PAC pseudo instruction. Is AsmPrinter, it is expanded into an actual PAC*
2160+
// instruction immediately preceded by the discriminator computation.
2161+
// This enforces the expected immediate modifier is used for signing, even
2162+
// if an attacker is able to substitute AddrDisc.
2163+
def PAC : Pseudo<(outs GPR64:$SignedVal),
2164+
(ins GPR64:$Val, i32imm:$Key, i64imm:$Disc, GPR64noip:$AddrDisc),
2165+
[], "$SignedVal = $Val">, Sched<[WriteI, ReadI]> {
2166+
let isCodeGenOnly = 1;
2167+
let hasSideEffects = 0;
2168+
let mayStore = 0;
2169+
let mayLoad = 0;
2170+
let Size = 12;
2171+
let Defs = [X17];
2172+
let usesCustomInserter = 1;
2173+
}
2174+
2175+
def : Pat<(int_ptrauth_sign GPR64:$Val, timm:$Key, GPR64noip:$AddrDisc),
2176+
(PAC GPR64:$Val, $Key, 0, GPR64noip:$AddrDisc)>;
2177+
21592178
// AUT and re-PAC a value, using different keys/data.
21602179
// This directly manipulates x16/x17, which are the only registers that
21612180
// certain OSs guarantee are safe to use for sensitive operations.
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \
3+
; RUN: | FileCheck %s --check-prefixes=DAGISEL
4+
; RUN: llc < %s -mtriple arm64e-apple-darwin -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \
5+
; RUN: | FileCheck %s --check-prefixes=GISEL
6+
; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \
7+
; RUN: | FileCheck %s --check-prefixes=DAGISEL
8+
; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \
9+
; RUN: | FileCheck %s --check-prefixes=GISEL
10+
11+
; Check MIR produced by the instruction selector to validate properties that
12+
; cannot be reliably tested by only inspecting the final asm output.
13+
14+
@discvar = dso_local global i64 0
15+
16+
; Make sure the components of blend(addr, imm) are recognized and passed to
17+
; PAC pseudo via separate operands to prevent substitution of the immediate
18+
; modifier.
19+
;
20+
; MIR output of the instruction selector is inspected, as it is hard to reliably
21+
; distinguish MOVKXi immediately followed by a pseudo from a standalone pseudo
22+
; instruction carrying address and immediate modifiers in its separate operands
23+
; by only observing the final asm output.
24+
25+
define i64 @small_imm_disc(i64 %addr) {
26+
; DAGISEL-LABEL: name: small_imm_disc
27+
; DAGISEL: bb.0.entry:
28+
; DAGISEL-NEXT: liveins: $x0
29+
; DAGISEL-NEXT: {{ $}}
30+
; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
31+
; DAGISEL-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 42
32+
; DAGISEL-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64noip = SUBREG_TO_REG 0, killed [[MOVi32imm]], %subreg.sub_32
33+
; DAGISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 42, killed $noreg, implicit-def dead $x17
34+
; DAGISEL-NEXT: $x0 = COPY [[PAC]]
35+
; DAGISEL-NEXT: RET_ReallyLR implicit $x0
36+
;
37+
; GISEL-LABEL: name: small_imm_disc
38+
; GISEL: bb.1.entry:
39+
; GISEL-NEXT: liveins: $x0
40+
; GISEL-NEXT: {{ $}}
41+
; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
42+
; GISEL-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 42
43+
; GISEL-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64noip = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
44+
; GISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 42, $noreg, implicit-def dead $x17
45+
; GISEL-NEXT: $x0 = COPY [[PAC]]
46+
; GISEL-NEXT: RET_ReallyLR implicit $x0
47+
entry:
48+
%signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 42)
49+
ret i64 %signed
50+
}
51+
52+
define i64 @large_imm_disc_wreg(i64 %addr) {
53+
; DAGISEL-LABEL: name: large_imm_disc_wreg
54+
; DAGISEL: bb.0.entry:
55+
; DAGISEL-NEXT: liveins: $x0
56+
; DAGISEL-NEXT: {{ $}}
57+
; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
58+
; DAGISEL-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 12345678
59+
; DAGISEL-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64noip = SUBREG_TO_REG 0, killed [[MOVi32imm]], %subreg.sub_32
60+
; DAGISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 0, killed [[SUBREG_TO_REG]], implicit-def dead $x17
61+
; DAGISEL-NEXT: $x0 = COPY [[PAC]]
62+
; DAGISEL-NEXT: RET_ReallyLR implicit $x0
63+
;
64+
; GISEL-LABEL: name: large_imm_disc_wreg
65+
; GISEL: bb.1.entry:
66+
; GISEL-NEXT: liveins: $x0
67+
; GISEL-NEXT: {{ $}}
68+
; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
69+
; GISEL-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 12345678
70+
; GISEL-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64noip = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
71+
; GISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 0, [[SUBREG_TO_REG]], implicit-def dead $x17
72+
; GISEL-NEXT: $x0 = COPY [[PAC]]
73+
; GISEL-NEXT: RET_ReallyLR implicit $x0
74+
entry:
75+
%signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 12345678)
76+
ret i64 %signed
77+
}
78+
79+
define i64 @large_imm_disc_xreg(i64 %addr) {
80+
; DAGISEL-LABEL: name: large_imm_disc_xreg
81+
; DAGISEL: bb.0.entry:
82+
; DAGISEL-NEXT: liveins: $x0
83+
; DAGISEL-NEXT: {{ $}}
84+
; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
85+
; DAGISEL-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64noip = MOVi64imm 123456789012345
86+
; DAGISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 0, killed [[MOVi64imm]], implicit-def dead $x17
87+
; DAGISEL-NEXT: $x0 = COPY [[PAC]]
88+
; DAGISEL-NEXT: RET_ReallyLR implicit $x0
89+
;
90+
; GISEL-LABEL: name: large_imm_disc_xreg
91+
; GISEL: bb.1.entry:
92+
; GISEL-NEXT: liveins: $x0
93+
; GISEL-NEXT: {{ $}}
94+
; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
95+
; GISEL-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64noip = MOVi64imm 123456789012345
96+
; GISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 0, [[MOVi64imm]], implicit-def dead $x17
97+
; GISEL-NEXT: $x0 = COPY [[PAC]]
98+
; GISEL-NEXT: RET_ReallyLR implicit $x0
99+
entry:
100+
%signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 123456789012345)
101+
ret i64 %signed
102+
}
103+
104+
define i64 @blend_and_sign_same_bb(i64 %addr) {
105+
; DAGISEL-LABEL: name: blend_and_sign_same_bb
106+
; DAGISEL: bb.0.entry:
107+
; DAGISEL-NEXT: liveins: $x0
108+
; DAGISEL-NEXT: {{ $}}
109+
; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
110+
; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar
111+
; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar)
112+
; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48
113+
; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]]
114+
; DAGISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 42, killed [[COPY1]], implicit-def dead $x17
115+
; DAGISEL-NEXT: $x0 = COPY [[PAC]]
116+
; DAGISEL-NEXT: RET_ReallyLR implicit $x0
117+
;
118+
; GISEL-LABEL: name: blend_and_sign_same_bb
119+
; GISEL: bb.1.entry:
120+
; GISEL-NEXT: liveins: $x0
121+
; GISEL-NEXT: {{ $}}
122+
; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
123+
; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar
124+
; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar)
125+
; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48
126+
; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY [[LDRXui]]
127+
; GISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 42, [[COPY1]], implicit-def dead $x17
128+
; GISEL-NEXT: $x0 = COPY [[PAC]]
129+
; GISEL-NEXT: RET_ReallyLR implicit $x0
130+
entry:
131+
%addrdisc = load i64, ptr @discvar
132+
%disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42)
133+
%signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 %disc)
134+
ret i64 %signed
135+
}
136+
137+
; In the below test cases both %addrdisc and %disc are computed (i.e. they are
138+
; neither global addresses, nor function arguments) in a different basic block,
139+
; making them harder to express via ISD::PtrAuthGlobalAddress.
140+
141+
define i64 @blend_and_sign_different_bbs(i64 %addr, i64 %cond) {
142+
; DAGISEL-LABEL: name: blend_and_sign_different_bbs
143+
; DAGISEL: bb.0.entry:
144+
; DAGISEL-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000)
145+
; DAGISEL-NEXT: liveins: $x0, $x1
146+
; DAGISEL-NEXT: {{ $}}
147+
; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1
148+
; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0
149+
; DAGISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar
150+
; DAGISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui killed [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar)
151+
; DAGISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48
152+
; DAGISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64noip = COPY [[MOVKXi]]
153+
; DAGISEL-NEXT: CBZX [[COPY]], %bb.2
154+
; DAGISEL-NEXT: B %bb.1
155+
; DAGISEL-NEXT: {{ $}}
156+
; DAGISEL-NEXT: bb.1.next:
157+
; DAGISEL-NEXT: successors: %bb.2(0x80000000)
158+
; DAGISEL-NEXT: {{ $}}
159+
; DAGISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64common = COPY [[COPY2]]
160+
; DAGISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY3]]
161+
; DAGISEL-NEXT: {{ $}}
162+
; DAGISEL-NEXT: bb.2.exit:
163+
; DAGISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]]
164+
; DAGISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY1]], 2, 42, [[COPY4]], implicit-def dead $x17
165+
; DAGISEL-NEXT: $x0 = COPY [[PAC]]
166+
; DAGISEL-NEXT: RET_ReallyLR implicit $x0
167+
;
168+
; GISEL-LABEL: name: blend_and_sign_different_bbs
169+
; GISEL: bb.1.entry:
170+
; GISEL-NEXT: successors: %bb.2(0x50000000), %bb.3(0x30000000)
171+
; GISEL-NEXT: liveins: $x0, $x1
172+
; GISEL-NEXT: {{ $}}
173+
; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0
174+
; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
175+
; GISEL-NEXT: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) @discvar
176+
; GISEL-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) @discvar :: (dereferenceable load (s64) from @discvar)
177+
; GISEL-NEXT: [[MOVKXi:%[0-9]+]]:gpr64noip = MOVKXi [[LDRXui]], 42, 48
178+
; GISEL-NEXT: CBZX [[COPY1]], %bb.3
179+
; GISEL-NEXT: B %bb.2
180+
; GISEL-NEXT: {{ $}}
181+
; GISEL-NEXT: bb.2.next:
182+
; GISEL-NEXT: successors: %bb.3(0x80000000)
183+
; GISEL-NEXT: {{ $}}
184+
; GISEL-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY [[MOVKXi]]
185+
; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[COPY2]]
186+
; GISEL-NEXT: {{ $}}
187+
; GISEL-NEXT: bb.3.exit:
188+
; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]]
189+
; GISEL-NEXT: [[PAC:%[0-9]+]]:gpr64 = PAC [[COPY]], 2, 42, [[COPY3]], implicit-def dead $x17
190+
; GISEL-NEXT: $x0 = COPY [[PAC]]
191+
; GISEL-NEXT: RET_ReallyLR implicit $x0
192+
entry:
193+
%addrdisc = load i64, ptr @discvar
194+
%disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42)
195+
%cond.b = icmp ne i64 %cond, 0
196+
br i1 %cond.b, label %next, label %exit
197+
198+
next:
199+
call void asm sideeffect "nop", "r"(i64 %disc)
200+
br label %exit
201+
202+
exit:
203+
%signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 %disc)
204+
ret i64 %signed
205+
}

0 commit comments

Comments
 (0)