diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index c0a42485d461f..0c9581ad5e04f 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -347,40 +347,6 @@ static bool isZeroingInactiveLanes(SDValue Op) { } } -static std::tuple -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. - const auto *ConstDiscN = dyn_cast(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 NoRegister, which we'll later - // replace with XZR, or directly use a Z variant of the inst. when available. - if (!AddrDisc) - AddrDisc = DAG->getRegister(AArch64::NoRegister, MVT::i64); - - return std::make_tuple( - DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64), - AddrDisc); -} - AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, const AArch64Subtarget &STI) : TargetLowering(TM), Subtarget(&STI) { @@ -3130,6 +3096,10 @@ void AArch64TargetLowering::fixupBlendComponents( isUInt<16>(MaybeBlend->getOperand(1).getImm())) { AddrDisc = AArch64::NoRegister; IntDisc = MaybeBlend->getOperand(1).getImm(); + } else if (MaybeBlend->getOpcode() == AArch64::COPY && + MaybeBlend->getOperand(1).getReg() == AArch64::XZR) { + AddrDisc = AArch64::NoRegister; + IntDisc = 0; } } @@ -3266,6 +3236,22 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), &AArch64::GPR64noipRegClass); return BB; + case AArch64::AUTH_TCRETURN: + fixupBlendComponents(MI, BB, MI.getOperand(3), MI.getOperand(4), + &AArch64::tcGPR64RegClass); + return BB; + case AArch64::AUTH_TCRETURN_BTI: + fixupBlendComponents(MI, BB, MI.getOperand(3), MI.getOperand(4), + &AArch64::tcGPRnotx16x17RegClass); + return BB; + case AArch64::BLRA: + fixupBlendComponents(MI, BB, MI.getOperand(2), MI.getOperand(3), + &AArch64::GPR64noipRegClass); + return BB; + case AArch64::BLRA_RVMARKER: + fixupBlendComponents(MI, BB, MI.getOperand(4), MI.getOperand(5), + &AArch64::GPR64noipRegClass); + return BB; } } @@ -9518,18 +9504,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) && "Invalid auth call key"); - // Split the discriminator into address/integer components. - SDValue AddrDisc, IntDisc; - std::tie(IntDisc, AddrDisc) = - extractPtrauthBlendDiscriminators(CLI.PAI->Discriminator, &DAG); - if (Opc == AArch64ISD::CALL_RVMARKER) Opc = AArch64ISD::AUTH_CALL_RVMARKER; else Opc = IsTailCall ? AArch64ISD::AUTH_TC_RETURN : AArch64ISD::AUTH_CALL; Ops.push_back(DAG.getTargetConstant(Key, DL, MVT::i32)); - Ops.push_back(IntDisc); - Ops.push_back(AddrDisc); + Ops.push_back(DAG.getTargetConstant(/*IntDisc=*/0, DL, MVT::i64)); + Ops.push_back(CLI.PAI->Discriminator); } // Add argument registers to the end of the list so that they are known live diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 35d96168a1518..67ecc6fc660e6 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2086,6 +2086,7 @@ let Predicates = [HasPAuth] in { let Size = 12; // 4 fixed + 8 variable, to compute discriminator. let Defs = [X16,X17,LR]; let Uses = [SP]; + let usesCustomInserter = 1; } def BLRA_RVMARKER : Pseudo< @@ -2098,6 +2099,7 @@ let Predicates = [HasPAuth] in { let isCall = 1; let Defs = [X16,X17,LR]; let Uses = [SP]; + let usesCustomInserter = 1; } // BRA pseudo, generalized version of BRAA/BRAB/Z. @@ -2242,7 +2244,7 @@ let Predicates = [HasPAuth] in { // make sure at least one register is usable as a scratch one - for that // purpose, use tcGPRnotx16x17 register class for one of the operands. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Size = 16, - Defs = [X16,X17], Uses = [SP] in { + usesCustomInserter = 1, Defs = [X16,X17], Uses = [SP] in { def AUTH_TCRETURN : Pseudo<(outs), (ins tcGPRnotx16x17:$dst, i32imm:$FPDiff, i32imm:$Key, i64imm:$Disc, tcGPR64:$AddrDisc), diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index 010d0aaa46e7f..056703dac179e 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -1169,15 +1169,9 @@ bool AArch64CallLowering::lowerTailCall( Info.PAI->Key == AArch64PACKey::IB) && "Invalid auth call key"); MIB.addImm(Info.PAI->Key); - - Register AddrDisc = 0; - uint16_t IntDisc = 0; - std::tie(IntDisc, AddrDisc) = - extractPtrauthBlendDiscriminators(Info.PAI->Discriminator, MRI); - - MIB.addImm(IntDisc); - MIB.addUse(AddrDisc); - if (AddrDisc != AArch64::NoRegister) { + MIB.addImm(/*IntDisc=*/0); + MIB.addUse(Info.PAI->Discriminator); + if (Info.PAI->Discriminator != AArch64::NoRegister) { MIB->getOperand(4).setReg(constrainOperandRegClass( MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(), *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), @@ -1443,15 +1437,9 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, Info.PAI->Key == AArch64PACKey::IB) && "Invalid auth call key"); MIB.addImm(Info.PAI->Key); - - Register AddrDisc = 0; - uint16_t IntDisc = 0; - std::tie(IntDisc, AddrDisc) = - extractPtrauthBlendDiscriminators(Info.PAI->Discriminator, MRI); - - MIB.addImm(IntDisc); - MIB.addUse(AddrDisc); - if (AddrDisc != AArch64::NoRegister) { + MIB.addImm(/*IntDisc=*/0); + MIB.addUse(Info.PAI->Discriminator); + if (Info.PAI->Discriminator != AArch64::NoRegister) { constrainOperandRegClass(MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(), *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), MIB->getOperand(CalleeOpNo + 3), diff --git a/llvm/test/CodeGen/AArch64/ptrauth-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-call.ll index 700686b9f194b..c366774600134 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-call.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-call.ll @@ -202,9 +202,9 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 { ; DARWIN-NEXT: mov x17, x0 ; DARWIN-NEXT: movk x17, #6503, lsl #48 ; DARWIN-NEXT: autda x16, x17 -; DARWIN-NEXT: ldr x8, [x16] +; DARWIN-NEXT: ldr x9, [x16] ; DARWIN-NEXT: movk x16, #34646, lsl #48 -; DARWIN-NEXT: blraa x8, x16 +; DARWIN-NEXT: blraa x9, x16 ; DARWIN-NEXT: mov w0, #42 ; DARWIN-NEXT: ldp x29, x30, [sp], #16 ; ELF-NEXT: str x30, [sp, #-16]! diff --git a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll index 2ce8732005aa6..05366ee02753b 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll @@ -511,3 +511,219 @@ exit: %resigned = call i64 @llvm.ptrauth.resign(i64 %addr, i32 2, i64 %auth.disc, i32 3, i64 %sign.disc) ret i64 %resigned } + +; Test other pseudo instructions accepting discriminator components as separate +; operands: AUTH_TCRETURN, AUTH_TCRETURN_BTI and BLRA. +; FIXME: Test BLRA_RVMARKER. +; +; A few other PAuth-related pseudo instructions exist that accept address and +; integer discriminator components, but the way they are currently selected both +; by DAGISel and GlobalISel is not susceptible to this issue: +; * MOVaddrPAC and LOADgotPAC are only emitted when lowering `ptrauth` constants +; in LLVM IR, so their discriminators are never expressed via blend. +; * BRA is only emitted for indirect branch, and its address discriminator is +; always XZR. +; +; Furthermore, a few more pseudo instructions have HasPAuth in their predicates, +; but only have constant discriminator or no discriminator operands at all: +; LOADgotAUTH and LOADauthptrstatic. +; +; The below test cases specify non-default preserve_nonecc calling convention - +; this is to prevent meaningless divergence between Darwin and ELF targets due +; to difference in callee-saved register masks specified in call instructions. + +define preserve_nonecc i64 @auth_tcreturn_blend_components(ptr %callee, i1 %cond.b) { + ; DAGISEL-LABEL: name: auth_tcreturn_blend_components + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; DAGISEL-NEXT: liveins: $x20, $w0 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:tcgprnotx16x17 = COPY $x20 + ; 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]+]]:tcgpr64 = COPY [[MOVKXi]] + ; DAGISEL-NEXT: TBZW [[COPY]], 0, %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: [[COPY4:%[0-9]+]]:tcgpr64 = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUTH_TCRETURN [[COPY1]], 0, 1, 42, [[COPY4]], csr_aarch64_noneregs, implicit-def dead $x16, implicit-def dead $x17, implicit $sp + ; + ; GISEL-LABEL: name: auth_tcreturn_blend_components + ; GISEL: bb.1.entry: + ; GISEL-NEXT: successors: %bb.2(0x40000000), %bb.3(0x40000000) + ; GISEL-NEXT: liveins: $w0, $x20 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:tcgprnotx16x17 = COPY $x20 + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w0 + ; 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]+]]:tcgpr64 = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: TBZW [[COPY1]], 0, %bb.3 + ; GISEL-NEXT: B %bb.2 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.2.next: + ; GISEL-NEXT: successors: %bb.3(0x80000000) + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[MOVKXi]] + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.3.exit: + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:tcgpr64 = COPY [[LDRXui]] + ; GISEL-NEXT: AUTH_TCRETURN [[COPY]], 0, 1, 42, [[COPY2]], csr_aarch64_noneregs, implicit-def $x16, implicit-def $x17, implicit $sp +entry: + %addrdisc = load i64, ptr @discvar + %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + br i1 %cond.b, label %next, label %exit + +next: + call void asm sideeffect "nop", "r"(i64 %disc) + br label %exit + +exit: + %result = tail call preserve_nonecc i64 %callee() [ "ptrauth"(i32 1, i64 %disc) ] + ret i64 %result +} + +define preserve_nonecc i64 @auth_tcreturn_bti_blend_components(ptr %callee, i1 %cond.b) "branch-target-enforcement"="true" { + ; DAGISEL-LABEL: name: auth_tcreturn_bti_blend_components + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; DAGISEL-NEXT: liveins: $x20, $w0 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x20 + ; 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]+]]:tcgprnotx16x17 = COPY [[MOVKXi]] + ; DAGISEL-NEXT: TBZW [[COPY]], 0, %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: [[COPY4:%[0-9]+]]:tcgprx16x17 = COPY [[COPY1]] + ; DAGISEL-NEXT: [[COPY5:%[0-9]+]]:tcgprnotx16x17 = COPY [[LDRXui]] + ; DAGISEL-NEXT: AUTH_TCRETURN_BTI [[COPY4]], 0, 1, 42, [[COPY5]], csr_aarch64_noneregs, implicit-def dead $x16, implicit-def dead $x17, implicit $sp + ; + ; GISEL-LABEL: name: auth_tcreturn_bti_blend_components + ; GISEL: bb.1.entry: + ; GISEL-NEXT: successors: %bb.2(0x40000000), %bb.3(0x40000000) + ; GISEL-NEXT: liveins: $w0, $x20 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:tcgprx16x17 = COPY $x20 + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w0 + ; 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]+]]:tcgprnotx16x17 = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: TBZW [[COPY1]], 0, %bb.3 + ; GISEL-NEXT: B %bb.2 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.2.next: + ; GISEL-NEXT: successors: %bb.3(0x80000000) + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 3866633 /* reguse:GPR64common */, [[MOVKXi]] + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: bb.3.exit: + ; GISEL-NEXT: [[COPY2:%[0-9]+]]:tcgprnotx16x17 = COPY [[LDRXui]] + ; GISEL-NEXT: AUTH_TCRETURN_BTI [[COPY]], 0, 1, 42, [[COPY2]], csr_aarch64_noneregs, implicit-def $x16, implicit-def $x17, implicit $sp +entry: + %addrdisc = load i64, ptr @discvar + %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + br i1 %cond.b, label %next, label %exit + +next: + call void asm sideeffect "nop", "r"(i64 %disc) + br label %exit + +exit: + %result = tail call preserve_nonecc i64 %callee() [ "ptrauth"(i32 1, i64 %disc) ] + ret i64 %result +} + +define preserve_nonecc i64 @blra_blend_components(ptr %callee, i1 %cond.b) { + ; DAGISEL-LABEL: name: blra_blend_components + ; DAGISEL: bb.0.entry: + ; DAGISEL-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; DAGISEL-NEXT: liveins: $x20, $w0 + ; DAGISEL-NEXT: {{ $}} + ; DAGISEL-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; DAGISEL-NEXT: [[COPY1:%[0-9]+]]:gpr64noip = COPY $x20 + ; 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]+]]:gpr64 = COPY [[MOVKXi]] + ; DAGISEL-NEXT: TBZW [[COPY]], 0, %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: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; DAGISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; DAGISEL-NEXT: BLRA [[COPY1]], 1, 42, [[COPY4]], csr_aarch64_noneregs, implicit-def dead $x16, implicit-def dead $x17, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0 + ; DAGISEL-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; DAGISEL-NEXT: [[COPY5:%[0-9]+]]:gpr64sp = COPY $x0 + ; DAGISEL-NEXT: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri [[COPY5]], 123, 0 + ; DAGISEL-NEXT: $x0 = COPY [[ADDXri]] + ; DAGISEL-NEXT: RET_ReallyLR implicit $x0 + ; + ; GISEL-LABEL: name: blra_blend_components + ; GISEL: bb.1.entry: + ; GISEL-NEXT: successors: %bb.2(0x40000000), %bb.3(0x40000000) + ; GISEL-NEXT: liveins: $w0, $x20 + ; GISEL-NEXT: {{ $}} + ; GISEL-NEXT: [[COPY:%[0-9]+]]:gpr64noip = COPY $x20 + ; GISEL-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w0 + ; 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]+]]:gpr64 = MOVKXi [[LDRXui]], 42, 48 + ; GISEL-NEXT: TBZW [[COPY1]], 0, %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: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp + ; GISEL-NEXT: [[COPY3:%[0-9]+]]:gpr64noip = COPY [[LDRXui]] + ; GISEL-NEXT: BLRA [[COPY]], 1, 42, [[COPY3]], csr_aarch64_noneregs, implicit-def $x16, implicit-def $x17, implicit-def $lr, implicit $sp, implicit-def $x0 + ; GISEL-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp + ; GISEL-NEXT: [[COPY4:%[0-9]+]]:gpr64sp = COPY $x0 + ; GISEL-NEXT: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri [[COPY4]], 123, 0 + ; GISEL-NEXT: $x0 = COPY [[ADDXri]] + ; GISEL-NEXT: RET_ReallyLR implicit $x0 +entry: + %addrdisc = load i64, ptr @discvar + %disc = call i64 @llvm.ptrauth.blend(i64 %addrdisc, i64 42) + br i1 %cond.b, label %next, label %exit + +next: + call void asm sideeffect "nop", "r"(i64 %disc) + br label %exit + +exit: + %tmp = call preserve_nonecc i64 %callee() [ "ptrauth"(i32 1, i64 %disc) ] + ; Prevent tail call. + %result = add i64 %tmp, 123 + ret i64 %result +}