Skip to content

[AArch64] Support preserve_none calling convention #91046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 3, 2024
Merged
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3068,7 +3068,8 @@ def M68kRTD: DeclOrTypeAttr {
let Documentation = [M68kRTDDocs];
}

def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86> {
def PreserveNone : DeclOrTypeAttr,
TargetSpecificAttr<TargetArch<!listconcat(TargetAArch64.Arches, TargetAnyX86.Arches)>> {
let Spellings = [Clang<"preserve_none">];
let Subjects = SubjectList<[FunctionLike]>;
let Documentation = [PreserveNoneDocs];
Expand Down
17 changes: 10 additions & 7 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -5660,18 +5660,21 @@ experimental at this time.
def PreserveNoneDocs : Documentation {
let Category = DocCatCallingConvs;
let Content = [{
On X86-64 target, this attribute changes the calling convention of a function.
On X86-64 and AArch64 targets, this attribute changes the calling convention of a function.
The ``preserve_none`` calling convention tries to preserve as few general
registers as possible. So all general registers are caller saved registers. It
also uses more general registers to pass arguments. This attribute doesn't
impact floating-point registers (XMMs/YMMs). Floating-point registers still
follow the c calling convention. ``preserve_none``'s ABI is still unstable, and
impact floating-point registers. ``preserve_none``'s ABI is still unstable, and
may be changed in the future.

- Only RSP and RBP are preserved by callee.

- Register R12, R13, R14, R15, RDI, RSI, RDX, RCX, R8, R9, R11, and RAX now can
be used to pass function arguments.
- On X86-64, only RSP and RBP are preserved by the callee.
Registers R12, R13, R14, R15, RDI, RSI, RDX, RCX, R8, R9, R11, and RAX now can
be used to pass function arguments. Floating-point registers (XMMs/YMMs) still
follow the C calling convention.
- On AArch64, only LR and FP are preserved by the callee.
Registers X19-X28, X0-X7, and X9-X15 are used to pass function arguments.
X8, X16-X18, SIMD and floating-point registers follow the AAPCS calling
convention.
}];
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_SwiftAsync:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_PreserveNone:
case CC_OpenCLKernel:
case CC_AArch64VectorCall:
case CC_AArch64SVEPCS:
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGen/preserve-call-conv.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,X86-LINUX
// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm < %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,LINUX
// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,LINUX

// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
Expand All @@ -23,5 +23,5 @@ void boo(void) __attribute__((preserve_all)) {
// is lowered to the corresponding calling convention attrribute at the LLVM IR
// level.
void bar(void) __attribute__((preserve_none)) {
// X86-LINUX-LABEL: define {{(dso_local )?}}preserve_nonecc void @bar()
// LINUX-LABEL: define {{(dso_local )?}}preserve_nonecc void @bar()
}
2 changes: 1 addition & 1 deletion llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ added in the future:
registers to pass arguments. This attribute doesn't impact non-general
purpose registers (e.g. floating point registers, on X86 XMMs/YMMs).
Non-general purpose registers still follow the standard c calling
convention. Currently it is for x86_64 only.
convention. Currently it is for x86_64 and AArch64 only.
"``cxx_fast_tlscc``" - The `CXX_FAST_TLS` calling convention for access functions
Clang generates an access function to access C++-style TLS. The access
function generally has an entry block, an exit block and an initialization
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64CallingConvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ bool CC_AArch64_Arm64EC_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT,
bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
CCState &State);
bool CC_AArch64_Preserve_None(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State);
bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
CCState &State);
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/Target/AArch64/AArch64CallingConvention.td
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,32 @@ def CC_AArch64_GHC : CallingConv<[
CCIfType<[i64], CCAssignToReg<[X19, X20, X21, X22, X23, X24, X25, X26, X27, X28]>>
]>;

let Entry = 1 in
def CC_AArch64_Preserve_None : CallingConv<[
// We can pass arguments in all general registers, except:
// - X8, used for sret
// - X16/X17, used by the linker as IP0/IP1
// - X18, the platform register
// - X29, the frame pointer
// - X30, the link register
// General registers are not preserved with the exception of
// FP, LR, and X18
// Non-volatile registers are used first, so functions may call
// normal functions without saving and reloading arguments.
CCIfType<[i32], CCAssignToReg<[W19, W20, W21, W22, W23,
W24, W25, W26, W27, W28,
W0, W1, W2, W3, W4, W5,
W6, W7, W9, W10, W11,
W12, W13, W14, W15]>>,
CCIfType<[i64], CCAssignToReg<[X19, X20, X21, X22, X23,
X24, X25, X26, X27, X28,
X0, X1, X2, X3, X4, X5,
X6, X7, X9, X10, X11,
X12, X13, X14, X15]>>,

CCDelegateTo<CC_AArch64_AAPCS>
]>;

// The order of the callee-saves in this file is important, because the
// FrameLowering code will use this order to determine the layout the
// callee-save area in the stack frame. As can be observed below, Darwin
Expand Down Expand Up @@ -606,6 +632,8 @@ def CSR_AArch64_AllRegs

def CSR_AArch64_NoRegs : CalleeSavedRegs<(add)>;

def CSR_AArch64_NoneRegs : CalleeSavedRegs<(add LR, FP)>;

def CSR_AArch64_RT_MostRegs : CalleeSavedRegs<(add CSR_AArch64_AAPCS,
(sequence "X%u", 9, 15))>;

Expand Down Expand Up @@ -681,6 +709,8 @@ def CSR_Darwin_AArch64_RT_AllRegs
// These all preserve x18 in addition to any other registers.
def CSR_AArch64_NoRegs_SCS
: CalleeSavedRegs<(add CSR_AArch64_NoRegs, X18)>;
def CSR_AArch64_NoneRegs_SCS
: CalleeSavedRegs<(add CSR_AArch64_NoneRegs, X18)>;
def CSR_AArch64_AllRegs_SCS
: CalleeSavedRegs<(add CSR_AArch64_AllRegs, X18)>;
def CSR_AArch64_AAPCS_SwiftError_SCS
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6961,6 +6961,8 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
report_fatal_error("Unsupported calling convention.");
case CallingConv::GHC:
return CC_AArch64_GHC;
case CallingConv::PreserveNone:
return CC_AArch64_Preserve_None;
case CallingConv::C:
case CallingConv::Fast:
case CallingConv::PreserveMost:
Expand Down Expand Up @@ -7483,6 +7485,20 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
FuncInfo->setLazySaveTPIDR2Obj(TPIDR2Obj);
}

if (CallConv == CallingConv::PreserveNone) {
for (const ISD::InputArg &I : Ins) {
if (I.Flags.isSwiftSelf() || I.Flags.isSwiftError() ||
I.Flags.isSwiftAsync()) {
MachineFunction &MF = DAG.getMachineFunction();
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
MF.getFunction(),
"Swift attributes can't be used with preserve_none",
DL.getDebugLoc()));
break;
}
}
}

return Chain;
}

Expand Down Expand Up @@ -7654,6 +7670,7 @@ static bool mayTailCallThisCC(CallingConv::ID CC) {
case CallingConv::AArch64_SVE_VectorCall:
case CallingConv::PreserveMost:
case CallingConv::PreserveAll:
case CallingConv::PreserveNone:
case CallingConv::Swift:
case CallingConv::SwiftTail:
case CallingConv::Tail:
Expand Down Expand Up @@ -8728,6 +8745,20 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
}
}

if (CallConv == CallingConv::PreserveNone) {
for (const ISD::OutputArg &O : Outs) {
if (O.Flags.isSwiftSelf() || O.Flags.isSwiftError() ||
O.Flags.isSwiftAsync()) {
MachineFunction &MF = DAG.getMachineFunction();
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
MF.getFunction(),
"Swift attributes can't be used with preserve_none",
DL.getDebugLoc()));
break;
}
}
}

return Result;
}

Expand Down
12 changes: 9 additions & 3 deletions llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
// GHC set of callee saved regs is empty as all those regs are
// used for passing STG regs around
return CSR_AArch64_NoRegs_SaveList;
if (MF->getFunction().getCallingConv() == CallingConv::PreserveNone)
return CSR_AArch64_NoneRegs_SaveList;
if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
return CSR_AArch64_AllRegs_SaveList;

Expand Down Expand Up @@ -260,6 +262,9 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
if (CC == CallingConv::GHC)
// This is academic because all GHC calls are (supposed to be) tail calls
return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
if (CC == CallingConv::PreserveNone)
return SCS ? CSR_AArch64_NoneRegs_SCS_RegMask
: CSR_AArch64_NoneRegs_RegMask;
if (CC == CallingConv::AnyReg)
return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;

Expand Down Expand Up @@ -294,12 +299,11 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
if (CC == CallingConv::PreserveMost)
return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
: CSR_AArch64_RT_MostRegs_RegMask;
else if (CC == CallingConv::PreserveAll)
if (CC == CallingConv::PreserveAll)
return SCS ? CSR_AArch64_RT_AllRegs_SCS_RegMask
: CSR_AArch64_RT_AllRegs_RegMask;

else
return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
}

const uint32_t *AArch64RegisterInfo::getCustomEHPadPreservedMask(
Expand Down Expand Up @@ -585,6 +589,8 @@ bool AArch64RegisterInfo::isArgumentRegister(const MachineFunction &MF,
report_fatal_error("Unsupported calling convention.");
case CallingConv::GHC:
return HasReg(CC_AArch64_GHC_ArgRegs, Reg);
case CallingConv::PreserveNone:
return HasReg(CC_AArch64_Preserve_None_ArgRegs, Reg);
case CallingConv::C:
case CallingConv::Fast:
case CallingConv::PreserveMost:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ static bool mayTailCallThisCC(CallingConv::ID CC) {
case CallingConv::C:
case CallingConv::PreserveMost:
case CallingConv::PreserveAll:
case CallingConv::PreserveNone:
case CallingConv::Swift:
case CallingConv::SwiftTail:
case CallingConv::Tail:
Expand Down
88 changes: 88 additions & 0 deletions llvm/test/CodeGen/AArch64/dynamic-regmask-preserve-none.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
; RUN: llc -mtriple=aarch64-apple-darwin -stop-after finalize-isel <%s | FileCheck %s

; Check that the callee doesn't have calleeSavedRegisters.
define preserve_nonecc i64 @callee1(i64 %a0, i64 %b0, i64 %c0, i64 %d0, i64 %e0) nounwind {
%a1 = mul i64 %a0, %b0
%a2 = mul i64 %a1, %c0
%a3 = mul i64 %a2, %d0
%a4 = mul i64 %a3, %e0
ret i64 %a4
}
; CHECK: name: callee1
; CHECK-NOT: calleeSavedRegisters:
; CHECK: RET_ReallyLR implicit $x0

; Check that RegMask is csr_aarch64_noneregs.
define i64 @caller1(i64 %a0) nounwind {
%b1 = call preserve_nonecc i64 @callee1(i64 %a0, i64 %a0, i64 %a0, i64 %a0, i64 %a0)
%b2 = add i64 %b1, %a0
ret i64 %b2
}
; CHECK: name: caller1
; CHECK: BL @callee1, csr_aarch64_noneregs
; CHECK: RET_ReallyLR implicit $x0


; Check that the callee doesn't have calleeSavedRegisters.
define preserve_nonecc {i64, i64} @callee2(i64 %a0, i64 %b0, i64 %c0, i64 %d0, i64 %e0) nounwind {
%a1 = mul i64 %a0, %b0
%a2 = mul i64 %a1, %c0
%a3 = mul i64 %a2, %d0
%a4 = mul i64 %a3, %e0
%b4 = insertvalue {i64, i64} undef, i64 %a3, 0
%b5 = insertvalue {i64, i64} %b4, i64 %a4, 1
ret {i64, i64} %b5
}
; CHECK: name: callee2
; CHECK-NOT: calleeSavedRegisters:
; CHECK: RET_ReallyLR implicit $x0


; Check that RegMask is csr_aarch64_noneregs.
define {i64, i64} @caller2(i64 %a0) nounwind {
%b1 = call preserve_nonecc {i64, i64} @callee2(i64 %a0, i64 %a0, i64 %a0, i64 %a0, i64 %a0)
ret {i64, i64} %b1
}
; CHECK: name: caller2
; CHECK: BL @callee2, csr_aarch64_noneregs
; CHECK: RET_ReallyLR implicit $x0


%struct.Large = type { i64, double, double }

; Declare the callee with a sret parameter.
declare preserve_nonecc void @callee3(ptr noalias nocapture writeonly sret(%struct.Large) align 4 %a0, i64 %b0) nounwind;

; Check that RegMask is csr_aarch64_noneregs.
define void @caller3(i64 %a0) nounwind {
%a1 = alloca %struct.Large, align 8
call preserve_nonecc void @callee3(ptr nonnull sret(%struct.Large) align 8 %a1, i64 %a0)
ret void
}
; CHECK: name: caller3
; CHECK: BL @callee3, csr_aarch64_noneregs
; CHECK: RET_ReallyLR


; Check that the callee doesn't have calleeSavedRegisters.
define preserve_nonecc {i64, double} @callee4(i64 %a0, i64 %b0, i64 %c0, i64 %d0, i64 %e0) nounwind {
%a1 = mul i64 %a0, %b0
%a2 = mul i64 %a1, %c0
%a3 = mul i64 %a2, %d0
%a4 = mul i64 %a3, %e0
%b4 = insertvalue {i64, double} undef, i64 %a3, 0
%b5 = insertvalue {i64, double} %b4, double 1.2, 1
ret {i64, double} %b5
}
; CHECK: name: callee4
; CHECK-NOT: calleeSavedRegisters:
; CHECK: RET_ReallyLR implicit $x0, implicit $d0

; Check that RegMask is csr_aarch64_noneregs.
define {i64, double} @caller4(i64 %a0) nounwind {
%b1 = call preserve_nonecc {i64, double} @callee4(i64 %a0, i64 %a0, i64 %a0, i64 %a0, i64 %a0)
ret {i64, double} %b1
}
; CHECK: name: caller4
; CHECK: BL @callee4, csr_aarch64_noneregs
; CHECK: RET_ReallyLR implicit $x0, implicit $d0
9 changes: 8 additions & 1 deletion llvm/test/CodeGen/AArch64/preserve.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ define preserve_allcc void @foo() #0 {
call void @bar2()
ret void
}
define preserve_nonecc void @qux() #0 {
; CHECK: qux Clobbered Registers: $ffr $fpcr $fpsr $nzcv $sp $vg $wsp $za $b0 $b1 $b2 $b3 $b4 $b5 $b6 $b7 $b16 $b17 $b18 $b19 $b20 $b21 $b22 $b23 $b24 $b25 $b26 $b27 $b28 $b29 $b30 $b31 $d0 $d1 $d2 $d3 $d4 $d5 $d6 $d7 $d16 $d17 $d18 $d19 $d20 $d21 $d22 $d23 $d24 $d25 $d26 $d27 $d28 $d29 $d30 $d31 $h0 $h1 $h2 $h3 $h4 $h5 $h6 $h7 $h16 $h17 $h18 $h19 $h20 $h21 $h22 $h23 $h24 $h25 $h26 $h27 $h28 $h29 $h30 $h31 $p0 $p1 $p2 $p3 $p4 $p5 $p6 $p7 $p8 $p9 $p10 $p11 $p12 $p13 $p14 $p15 $pn0 $pn1 $pn2 $pn3 $pn4 $pn5 $pn6 $pn7 $pn8 $pn9 $pn10 $pn11 $pn12 $pn13 $pn14 $pn15 $q0 $q1 $q2 $q3 $q4 $q5 $q6 $q7 $q8 $q9 $q10 $q11 $q12 $q13 $q14 $q15 $q16 $q17 $q18 $q19 $q20 $q21 $q22 $q23 $q24 $q25 $q26 $q27 $q28 $q29 $q30 $q31 $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $s16 $s17 $s18 $s19 $s20 $s21 $s22 $s23 $s24 $s25 $s26 $s27 $s28 $s29 $s30 $s31 $w0 $w1 $w2 $w3 $w4 $w5 $w6 $w7 $w8 $w9 $w10 $w11 $w12 $w13 $w14 $w15 $w16 $w17 $w18 $x0 $x1 $x2 $x3 $x4 $x5 $x6 $x7 $x8 $x9 $x10 $x11 $x12 $x13 $x14 $x15 $x16 $x17 $x18 $z0 $z1 $z2 $z3 $z4 $z5 $z6 $z7 $z8 $z9 $z10 $z11 $z12 $z13 $z14 $z15 $z16 $z17 $z18 $z19 $z20 $z21 $z22 $z23 $z24 $z25 $z26 $z27 $z28 $z29 $z30 $z31 $zab0 $zad0 $zad1 $zad2 $zad3 $zad4 $zad5 $zad6 $zad7 $zah0 $zah1 $zaq0 $zaq1 $zaq2 $zaq3 $zaq4 $zaq5 $zaq6 $zaq7 $zaq8 $zaq9 $zaq10 $zaq11 $zaq12 $zaq13 $zaq14 $zaq15 $zas0 $zas1 $zas2 $zas3 $zt0 $d0_d1 $d1_d2 $d2_d3 $d3_d4 $d4_d5 $d5_d6 $d6_d7 $d7_d8 $d15_d16 $d16_d17 $d17_d18 $d18_d19 $d19_d20 $d20_d21 $d21_d22 $d22_d23 $d23_d24 $d24_d25 $d25_d26 $d26_d27 $d27_d28 $d28_d29 $d29_d30 $d30_d31 $d31_d0 $d0_d1_d2_d3 $d1_d2_d3_d4 $d2_d3_d4_d5 $d3_d4_d5_d6 $d4_d5_d6_d7 $d5_d6_d7_d8 $d6_d7_d8_d9 $d7_d8_d9_d10 $d13_d14_d15_d16 $d14_d15_d16_d17 $d15_d16_d17_d18 $d16_d17_d18_d19 $d17_d18_d19_d20 $d18_d19_d20_d21 $d19_d20_d21_d22 $d20_d21_d22_d23 $d21_d22_d23_d24 $d22_d23_d24_d25 $d23_d24_d25_d26 $d24_d25_d26_d27 $d25_d26_d27_d28 $d26_d27_d28_d29 $d27_d28_d29_d30 $d28_d29_d30_d31 $d29_d30_d31_d0 $d30_d31_d0_d1 $d31_d0_d1_d2 $d0_d1_d2 $d1_d2_d3 $d2_d3_d4 $d3_d4_d5 $d4_d5_d6 $d5_d6_d7 $d6_d7_d8 $d7_d8_d9 $d14_d15_d16 $d15_d16_d17 $d16_d17_d18 $d17_d18_d19 $d18_d19_d20 $d19_d20_d21 $d20_d21_d22 $d21_d22_d23 $d22_d23_d24 $d23_d24_d25 $d24_d25_d26 $d25_d26_d27 $d26_d27_d28 $d27_d28_d29 $d28_d29_d30 $d29_d30_d31 $d30_d31_d0 $d31_d0_d1 $p0_p1 $p1_p2 $p2_p3 $p3_p4 $p4_p5 $p5_p6 $p6_p7 $p7_p8 $p8_p9 $p9_p10 $p10_p11 $p11_p12 $p12_p13 $p13_p14 $p14_p15 $p15_p0 $q0_q1 $q1_q2 $q2_q3 $q3_q4 $q4_q5 $q5_q6 $q6_q7 $q7_q8 $q8_q9 $q9_q10 $q10_q11 $q11_q12 $q12_q13 $q13_q14 $q14_q15 $q15_q16 $q16_q17 $q17_q18 $q18_q19 $q19_q20 $q20_q21 $q21_q22 $q22_q23 $q23_q24 $q24_q25 $q25_q26 $q26_q27 $q27_q28 $q28_q29 $q29_q30 $q30_q31 $q31_q0 $q0_q1_q2_q3 $q1_q2_q3_q4 $q2_q3_q4_q5 $q3_q4_q5_q6 $q4_q5_q6_q7 $q5_q6_q7_q8 $q6_q7_q8_q9 $q7_q8_q9_q10 $q8_q9_q10_q11 $q9_q10_q11_q12 $q10_q11_q12_q13 $q11_q12_q13_q14 $q12_q13_q14_q15 $q13_q14_q15_q16 $q14_q15_q16_q17 $q15_q16_q17_q18 $q16_q17_q18_q19 $q17_q18_q19_q20 $q18_q19_q20_q21 $q19_q20_q21_q22 $q20_q21_q22_q23 $q21_q22_q23_q24 $q22_q23_q24_q25 $q23_q24_q25_q26 $q24_q25_q26_q27 $q25_q26_q27_q28 $q26_q27_q28_q29 $q27_q28_q29_q30 $q28_q29_q30_q31 $q29_q30_q31_q0 $q30_q31_q0_q1 $q31_q0_q1_q2 $q0_q1_q2 $q1_q2_q3 $q2_q3_q4 $q3_q4_q5 $q4_q5_q6 $q5_q6_q7 $q6_q7_q8 $q7_q8_q9 $q8_q9_q10 $q9_q10_q11 $q10_q11_q12 $q11_q12_q13 $q12_q13_q14 $q13_q14_q15 $q14_q15_q16 $q15_q16_q17 $q16_q17_q18 $q17_q18_q19 $q18_q19_q20 $q19_q20_q21 $q20_q21_q22 $q21_q22_q23 $q22_q23_q24 $q23_q24_q25 $q24_q25_q26 $q25_q26_q27 $q26_q27_q28 $q27_q28_q29 $q28_q29_q30 $q29_q30_q31 $q30_q31_q0 $q31_q0_q1 $x0_x1_x2_x3_x4_x5_x6_x7 $x2_x3_x4_x5_x6_x7_x8_x9 $x4_x5_x6_x7_x8_x9_x10_x11 $x6_x7_x8_x9_x10_x11_x12_x13 $x8_x9_x10_x11_x12_x13_x14_x15 $x10_x11_x12_x13_x14_x15_x16_x17 $x12_x13_x14_x15_x16_x17_x18_x19 $x14_x15_x16_x17_x18_x19_x20_x21 $x16_x17_x18_x19_x20_x21_x22_x23 $x18_x19_x20_x21_x22_x23_x24_x25 $w30_wzr $w0_w1 $w2_w3 $w4_w5 $w6_w7 $w8_w9 $w10_w11 $w12_w13 $w14_w15 $w16_w17 $w18_w19 $lr_xzr $x0_x1 $x2_x3 $x4_x5 $x6_x7 $x8_x9 $x10_x11 $x12_x13 $x14_x15 $x16_x17 $x18_x19 $z0_z1 $z1_z2 $z2_z3 $z3_z4 $z4_z5 $z5_z6 $z6_z7 $z7_z8 $z8_z9 $z9_z10 $z10_z11 $z11_z12 $z12_z13 $z13_z14 $z14_z15 $z15_z16 $z16_z17 $z17_z18 $z18_z19 $z19_z20 $z20_z21 $z21_z22 $z22_z23 $z23_z24 $z24_z25 $z25_z26 $z26_z27 $z27_z28 $z28_z29 $z29_z30 $z30_z31 $z31_z0 $z0_z1_z2_z3 $z1_z2_z3_z4 $z2_z3_z4_z5 $z3_z4_z5_z6 $z4_z5_z6_z7 $z5_z6_z7_z8 $z6_z7_z8_z9 $z7_z8_z9_z10 $z8_z9_z10_z11 $z9_z10_z11_z12 $z10_z11_z12_z13 $z11_z12_z13_z14 $z12_z13_z14_z15 $z13_z14_z15_z16 $z14_z15_z16_z17 $z15_z16_z17_z18 $z16_z17_z18_z19 $z17_z18_z19_z20 $z18_z19_z20_z21 $z19_z20_z21_z22 $z20_z21_z22_z23 $z21_z22_z23_z24 $z22_z23_z24_z25 $z23_z24_z25_z26 $z24_z25_z26_z27 $z25_z26_z27_z28 $z26_z27_z28_z29 $z27_z28_z29_z30 $z28_z29_z30_z31 $z29_z30_z31_z0 $z30_z31_z0_z1 $z31_z0_z1_z2 $z0_z1_z2 $z1_z2_z3 $z2_z3_z4 $z3_z4_z5 $z4_z5_z6 $z5_z6_z7 $z6_z7_z8 $z7_z8_z9 $z8_z9_z10 $z9_z10_z11 $z10_z11_z12 $z11_z12_z13 $z12_z13_z14 $z13_z14_z15 $z14_z15_z16 $z15_z16_z17 $z16_z17_z18 $z17_z18_z19 $z18_z19_z20 $z19_z20_z21 $z20_z21_z22 $z21_z22_z23 $z22_z23_z24 $z23_z24_z25 $z24_z25_z26 $z25_z26_z27 $z26_z27_z28 $z27_z28_z29 $z28_z29_z30 $z29_z30_z31 $z30_z31_z0 $z31_z0_z1 $z16_z24 $z17_z25 $z18_z26 $z19_z27 $z20_z28 $z21_z29 $z22_z30 $z23_z31 $z0_z8 $z1_z9 $z2_z10 $z3_z11 $z4_z12 $z5_z13 $z6_z14 $z7_z15 $z16_z20_z24_z28 $z17_z21_z25_z29 $z18_z22_z26_z30 $z19_z23_z27_z31 $z0_z4_z8_z12 $z1_z5_z9_z13 $z2_z6_z10_z14 $z3_z7_z11_z15

call void @bar1()
call void @bar2()
ret void
}
declare void @bar2()

@llvm.used = appending global [2 x ptr] [ptr @foo, ptr @baz]
@llvm.used = appending global [3 x ptr] [ptr @foo, ptr @baz, ptr @qux]

attributes #0 = {nounwind}
Loading
Loading