Skip to content

Commit

Permalink
New calling convention preserve_none (#76868)
Browse files Browse the repository at this point in the history
The new experimental calling convention preserve_none is the opposite
side of existing preserve_all. It tries to preserve as few general
registers as possible. So all general registers are caller saved
registers. It can also uses more general registers to pass arguments.
This attribute doesn't impact floating-point registers. Floating-point
registers still follow the c calling convention.

Currently preserve_none is supported on X86-64 only. It changes the c
calling convention in following fields:
  
* RSP and RBP are the only preserved general registers, all other
general registers are caller saved registers.
* We can use [RDI, RSI, RDX, RCX, R8, R9, R11, R12, R13, R14, R15, RAX]
to pass arguments.

It can improve the performance of hot tailcall chain, because many
callee saved registers' save/restore instructions can be removed if the
tail functions are using preserve_none. In my experiment in protocol
buffer, the parsing functions are improved by 3% to 10%.
  • Loading branch information
weiguozhi committed Feb 5, 2024
1 parent 7670609 commit c166a43
Show file tree
Hide file tree
Showing 38 changed files with 635 additions and 3 deletions.
1 change: 1 addition & 0 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -2986,6 +2986,7 @@ enum CXCallingConv {
CXCallingConv_SwiftAsync = 17,
CXCallingConv_AArch64SVEPCS = 18,
CXCallingConv_M68kRTD = 19,
CXCallingConv_PreserveNone = 20,

CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2959,6 +2959,12 @@ def M68kRTD: DeclOrTypeAttr {
let Documentation = [M68kRTDDocs];
}

def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86> {
let Spellings = [Clang<"preserve_none">];
let Subjects = SubjectList<[FunctionLike]>;
let Documentation = [PreserveNoneDocs];
}

def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"featuresStr">];
Expand Down
17 changes: 17 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -5506,6 +5506,23 @@ 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.
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.

- Only RSP and RBP are preserved by callee.

- Register RDI, RSI, RDX, RCX, R8, R9, R11, R12, R13, R14, R15 and RAX now can
be used to pass function arguments.
}];
}

def DeprecatedDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ namespace clang {
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
CC_M68kRTD, // __attribute__((m68k_rtd))
CC_PreserveNone, // __attribute__((preserve_none))
};

/// Checks whether the given calling convention supports variadic
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3443,6 +3443,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_PreserveMost:
case CC_PreserveAll:
case CC_M68kRTD:
case CC_PreserveNone:
// FIXME: we should be mangling all of the above.
return "";

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3438,6 +3438,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_PreserveMost: return "preserve_most";
case CC_PreserveAll: return "preserve_all";
case CC_M68kRTD: return "m68k_rtd";
case CC_PreserveNone: return "preserve_none";
}

llvm_unreachable("Invalid calling convention.");
Expand Down Expand Up @@ -3990,6 +3991,7 @@ bool AttributedType::isCallingConv() const {
case attr::PreserveMost:
case attr::PreserveAll:
case attr::M68kRTD:
case attr::PreserveNone:
return true;
}
llvm_unreachable("invalid attr kind");
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
case CC_M68kRTD:
OS << " __attribute__((m68k_rtd))";
break;
case CC_PreserveNone:
OS << " __attribute__((preserve_none))";
break;
}
}

Expand Down Expand Up @@ -1911,6 +1914,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::M68kRTD:
OS << "m68k_rtd";
break;
case attr::PreserveNone:
OS << "preserve_none";
break;
case attr::NoDeref:
OS << "noderef";
break;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
case CC_Win64:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_PreserveNone:
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
Expand Down Expand Up @@ -854,6 +855,7 @@ class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
case CC_IntelOclBicc:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_PreserveNone:
case CC_X86_64SysV:
case CC_Swift:
case CC_SwiftAsync:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_Swift: return llvm::CallingConv::Swift;
case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
case CC_M68kRTD: return llvm::CallingConv::M68k_RTD;
case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
}
}

Expand Down Expand Up @@ -256,6 +257,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
if (D->hasAttr<M68kRTDAttr>())
return CC_M68kRTD;

if (D->hasAttr<PreserveNoneAttr>())
return CC_PreserveNone;

return CC_C;
}

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,8 @@ static unsigned getDwarfCC(CallingConv CC) {
return llvm::dwarf::DW_CC_LLVM_X86RegCall;
case CC_M68kRTD:
return llvm::dwarf::DW_CC_LLVM_M68kRTD;
case CC_PreserveNone:
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
}
return 0;
}
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5235,6 +5235,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
case ParsedAttr::AT_M68kRTD:
D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL));
return;
case ParsedAttr::AT_PreserveNone:
D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL));
return;
default:
llvm_unreachable("unexpected attribute kind");
}
Expand Down Expand Up @@ -5441,6 +5444,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
case ParsedAttr::AT_M68kRTD:
CC = CC_M68kRTD;
break;
case ParsedAttr::AT_PreserveNone:
CC = CC_PreserveNone;
break;
default: llvm_unreachable("unexpected attribute kind");
}

Expand Down Expand Up @@ -9559,6 +9565,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_AArch64SVEPcs:
case ParsedAttr::AT_AMDGPUKernelCall:
case ParsedAttr::AT_M68kRTD:
case ParsedAttr::AT_PreserveNone:
handleCallConvAttr(S, D, AL);
break;
case ParsedAttr::AT_Suppress:
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
case ParsedAttr::AT_IntelOclBicc: \
case ParsedAttr::AT_PreserveMost: \
case ParsedAttr::AT_PreserveAll: \
case ParsedAttr::AT_M68kRTD
case ParsedAttr::AT_M68kRTD: \
case ParsedAttr::AT_PreserveNone

// Function type attributes.
#define FUNCTION_TYPE_ATTRS_CASELIST \
Expand Down Expand Up @@ -7919,6 +7920,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
case ParsedAttr::AT_M68kRTD:
return createSimpleAttr<M68kRTDAttr>(Ctx, Attr);
case ParsedAttr::AT_PreserveNone:
return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr);
}
llvm_unreachable("unexpected attribute kind!");
}
Expand Down
7 changes: 7 additions & 0 deletions clang/test/CodeGen/debug-info-cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
// CC_SwiftAsync, // __attribute__((swiftasynccall))
// CC_PreserveMost, // __attribute__((preserve_most))
// CC_PreserveAll, // __attribute__((preserve_all))
// CC_PreserveNone, // __attribute__((preserve_none))
// };

#ifdef __x86_64__
Expand Down Expand Up @@ -51,6 +52,12 @@ __attribute__((preserve_all)) int add_preserve_all(int a, int b) {
return a+b;
}

// LINUX: !DISubprogram({{.*}}"add_preserve_none", {{.*}}type: ![[FTY:[0-9]+]]
// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveNone,
__attribute__((preserve_none)) int add_preserve_none(int a, int b) {
return a+b;
}

// LINUX: !DISubprogram({{.*}}"add_swiftcall", {{.*}}type: ![[FTY:[0-9]+]]
// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift,
__attribute__((swiftcall)) int add_swiftcall(int a, int b) {
Expand Down
8 changes: 7 additions & 1 deletion clang/test/CodeGen/preserve-call-conv.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s | FileCheck %s
// 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-windows-msvc -emit-llvm %s -o - | FileCheck %s
Expand All @@ -19,3 +19,9 @@ void boo(void) __attribute__((preserve_all)) {
// CHECK-LABEL: define {{(dso_local )?}}preserve_allcc void @boo()
}

// Check that the preserve_none calling convention attribute at the source level
// 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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union)
// CHECK-NEXT: PreserveNone (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record)
// CHECK-NEXT: ReadOnlyPlacement (SubjectMatchRule_record)
// CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter)
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Sema/no_callconv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ void __attribute__((swiftasynccall)) funcKK() {} // expected-error {{'swiftasync
void __attribute__((pascal)) funcG() {} // expected-error {{'pascal' calling convention is not supported for this target}}
void __attribute__((preserve_most)) funcL() {} // expected-error {{'preserve_most' calling convention is not supported for this target}}
void __attribute__((preserve_all)) funcM() {} // expected-error {{'preserve_all' calling convention is not supported for this target}}
void __attribute__((preserve_none)) funcN() {} // expected-error {{'preserve_none' calling convention is not supported for this target}}
void __attribute__((stdcall)) funcD() {} // expected-error {{'stdcall' calling convention is not supported for this target}}
void __attribute__((fastcall)) funcE() {} // expected-error {{'fastcall' calling convention is not supported for this target}}
void __attribute__((thiscall)) funcF() {} // expected-error {{'thiscall' calling convention is not supported for this target}}
Expand All @@ -30,6 +31,7 @@ void __attribute__((swiftcall)) funcK() {}
void __attribute__((swiftasynccall)) funcKK() {}
void __attribute__((preserve_most)) funcL() {}
void __attribute__((preserve_all)) funcM() {}
void __attribute__((preserve_none)) funcN() {}

// Same function with different calling conventions. Error with a note pointing to the last decl.
void __attribute__((preserve_all)) funcR(); // expected-note {{previous declaration is here}}
Expand Down
19 changes: 19 additions & 0 deletions clang/test/Sema/preserve-none-call-conv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-unknown -verify

typedef void typedef_fun_t(int);

void __attribute__((preserve_none)) boo(void *ptr) {
}

void __attribute__((preserve_none(1))) boo1(void *ptr) { // expected-error {{'preserve_none' attribute takes no arguments}}
}

void (__attribute__((preserve_none)) *pboo1)(void *) = boo;

void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-error {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_none))'}}
void (*pboo3)(void *) = boo; // expected-error {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_none))'}}

typedef_fun_t typedef_fun_boo; // expected-note {{previous declaration is here}}
void __attribute__((preserve_none)) typedef_fun_boo(int x) { } // expected-error {{function declared 'preserve_none' here was previously declared without calling convention}}

struct type_test_boo {} __attribute__((preserve_none)); // expected-warning {{'preserve_none' attribute only applies to functions and function pointers}}
1 change: 1 addition & 0 deletions clang/tools/libclang/CXType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(PreserveMost);
TCALLINGCONV(PreserveAll);
TCALLINGCONV(M68kRTD);
TCALLINGCONV(PreserveNone);
case CC_SpirFunction: return CXCallingConv_Unexposed;
case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed;
case CC_OpenCLKernel: return CXCallingConv_Unexposed;
Expand Down
7 changes: 7 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ added in the future:
This calling convention, like the `PreserveMost` calling convention, will be
used by a future version of the ObjectiveC runtime and should be considered
experimental at this time.
"``preserve_nonecc``" - The `PreserveNone` calling convention
This calling convention doesn't preserve any general registers. So all
general registers are caller saved registers. It also uses all general
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.
"``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
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ enum Kind {
kw_swifttailcc,
kw_preserve_mostcc,
kw_preserve_allcc,
kw_preserve_nonecc,
kw_ghccc,
kw_x86_intrcc,
kw_hhvmcc,
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/Dwarf.def
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,7 @@ HANDLE_DW_CC(0xc9, LLVM_PreserveMost)
HANDLE_DW_CC(0xca, LLVM_PreserveAll)
HANDLE_DW_CC(0xcb, LLVM_X86RegCall)
HANDLE_DW_CC(0xcc, LLVM_M68kRTD)
HANDLE_DW_CC(0xcd, LLVM_PreserveNone)
// From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
// generated by any toolchain. It is used internally to GDB to indicate OpenCL
// C functions that have been compiled with the IBM XL C for OpenCL compiler and
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/CallingConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ namespace CallingConv {
/// their stack.
SwiftTail = 20,

/// Used for runtime calls that preserves none general registers.
PreserveNone = 21,

/// This is the start of the target-specific calling conventions, e.g.
/// fastcall and thiscall on X86.
FirstTargetCC = 64,
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(anyregcc);
KEYWORD(preserve_mostcc);
KEYWORD(preserve_allcc);
KEYWORD(preserve_nonecc);
KEYWORD(ghccc);
KEYWORD(x86_intrcc);
KEYWORD(hhvmcc);
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2109,6 +2109,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
/// ::= 'anyregcc'
/// ::= 'preserve_mostcc'
/// ::= 'preserve_allcc'
/// ::= 'preserve_nonecc'
/// ::= 'ghccc'
/// ::= 'swiftcc'
/// ::= 'swifttailcc'
Expand Down Expand Up @@ -2169,6 +2170,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
case lltok::kw_anyregcc: CC = CallingConv::AnyReg; break;
case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
case lltok::kw_preserve_nonecc:CC = CallingConv::PreserveNone; break;
case lltok::kw_ghccc: CC = CallingConv::GHC; break;
case lltok::kw_swiftcc: CC = CallingConv::Swift; break;
case lltok::kw_swifttailcc: CC = CallingConv::SwiftTail; break;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,9 @@ void DWARFTypePrinter::appendSubroutineNameAfter(
case CallingConvention::DW_CC_LLVM_PreserveAll:
OS << " __attribute__((preserve_all))";
break;
case CallingConvention::DW_CC_LLVM_PreserveNone:
OS << " __attribute__((preserve_none))";
break;
case CallingConvention::DW_CC_LLVM_X86RegCall:
OS << " __attribute__((regcall))";
break;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
case CallingConv::AnyReg: Out << "anyregcc"; break;
case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
case CallingConv::PreserveNone: Out << "preserve_nonecc"; break;
case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
case CallingConv::GHC: Out << "ghccc"; break;
case CallingConv::Tail: Out << "tailcc"; break;
Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/Target/X86/X86CallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,23 @@ def CC_Intel_OCL_BI : CallingConv<[
CCDelegateTo<CC_X86_32_C>
]>;

def CC_X86_64_Preserve_None : CallingConv<[
// We don't preserve general registers, so all of them can be used to pass
// arguments except
// - RBP frame pointer
// - R10 'nest' parameter
// - RBX base pointer
// - R16 - R31 these are not available everywhere
CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D,
R11D, R12D, R13D, R14D, R15D, EAX]>>,

CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8, R9,
R11, R12, R13, R14, R15, RAX]>>,

// Otherwise it's the same as the regular C calling convention.
CCDelegateTo<CC_X86_64_C>
]>;

//===----------------------------------------------------------------------===//
// X86 Root Argument Calling Conventions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1095,6 +1112,7 @@ def CC_X86_64 : CallingConv<[
CCIfCC<"CallingConv::X86_RegCall",
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_RegCall>>>,
CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_SysV64_RegCall>>,
CCIfCC<"CallingConv::PreserveNone", CCDelegateTo<CC_X86_64_Preserve_None>>,
CCIfCC<"CallingConv::X86_INTR", CCCustom<"CC_X86_Intr">>,

// Mingw64 and native Win64 use Win64 CC
Expand Down Expand Up @@ -1184,6 +1202,7 @@ def CSR_64_AllRegs_AVX512 : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX,
(sequence "ZMM%u", 0, 31),
(sequence "K%u", 0, 7)),
(sequence "XMM%u", 0, 15))>;
def CSR_64_NoneRegs : CalleeSavedRegs<(add RBP)>;

// Standard C + YMM6-15
def CSR_Win64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12,
Expand Down

0 comments on commit c166a43

Please sign in to comment.