[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/weiguozhi closed https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -0,0 +1,131 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=x86_64-unknown-unknown -mcpu=corei7 < %s | FileCheck %s + +; This test checks various function call behaviors between preserve_none and +; normal calling conventions. + +declare preserve_nonecc void @callee(ptr) + +; Normal caller calls preserve_none callee. Will not generated tail call because +; of incompatible calling convention. Callee saved registers are saved/restored +; around the call. +define void @caller1(ptr %a) { +; CHECK-LABEL: caller1: +; CHECK: # %bb.0: +; CHECK-NEXT:pushq %r15 +; CHECK-NEXT:.cfi_def_cfa_offset 16 +; CHECK-NEXT:pushq %r14 +; CHECK-NEXT:.cfi_def_cfa_offset 24 +; CHECK-NEXT:pushq %r13 +; CHECK-NEXT:.cfi_def_cfa_offset 32 +; CHECK-NEXT:pushq %r12 +; CHECK-NEXT:.cfi_def_cfa_offset 40 +; CHECK-NEXT:pushq %rbx +; CHECK-NEXT:.cfi_def_cfa_offset 48 +; CHECK-NEXT:.cfi_offset %rbx, -48 +; CHECK-NEXT:.cfi_offset %r12, -40 +; CHECK-NEXT:.cfi_offset %r13, -32 +; CHECK-NEXT:.cfi_offset %r14, -24 +; CHECK-NEXT:.cfi_offset %r15, -16 +; CHECK-NEXT:callq callee@PLT +; CHECK-NEXT:popq %rbx +; CHECK-NEXT:.cfi_def_cfa_offset 40 +; CHECK-NEXT:popq %r12 +; CHECK-NEXT:.cfi_def_cfa_offset 32 +; CHECK-NEXT:popq %r13 +; CHECK-NEXT:.cfi_def_cfa_offset 24 +; CHECK-NEXT:popq %r14 +; CHECK-NEXT:.cfi_def_cfa_offset 16 +; CHECK-NEXT:popq %r15 +; CHECK-NEXT:.cfi_def_cfa_offset 8 +; CHECK-NEXT:retq + tail call preserve_nonecc void @callee(ptr %a) + ret void +} + +; Preserve_none caller calls preserve_none callee. Same function body. +; The tail call is preserved. No registers are saved/restored around the call. +; Actually a simple jmp instruction is generated. +define preserve_nonecc void @caller2(ptr %a) { +; CHECK-LABEL: caller2: +; CHECK: # %bb.0: +; CHECK-NEXT:jmp callee@PLT # TAILCALL + tail call preserve_nonecc void @callee(ptr %a) + ret void +} + +; Preserve_none function can use more registers to pass parameters. +define preserve_nonecc i64 @callee_with_many_param(i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12) { david-xl wrote: or better yet, pass the arguments in order to (tail)call to another preserve_none callee. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/weiguozhi updated https://github.com/llvm/llvm-project/pull/76868 >From 90e14918a0eb13e2187f8548416ac72491d966c1 Mon Sep 17 00:00:00 2001 From: Guozhi Wei Date: Thu, 21 Dec 2023 19:04:44 + Subject: [PATCH 1/6] New calling convention preserve_none The new 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. --- clang/include/clang-c/Index.h | 1 + clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Basic/AttrDocs.td | 17 clang/include/clang/Basic/Specifiers.h| 1 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/Type.cpp| 2 + clang/lib/AST/TypePrinter.cpp | 6 ++ clang/lib/Basic/Targets/X86.h | 2 + clang/lib/CodeGen/CGCall.cpp | 4 + clang/lib/CodeGen/CGDebugInfo.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 7 ++ clang/lib/Sema/SemaType.cpp | 5 +- clang/test/CodeGen/debug-info-cc.c| 7 ++ clang/test/CodeGen/preserve-call-conv.c | 8 +- clang/test/Sema/no_callconv.cpp | 2 + clang/test/Sema/preserve-none-call-conv.c | 19 clang/tools/libclang/CXType.cpp | 1 + llvm/docs/LangRef.rst | 6 ++ llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/CallingConv.h| 3 + llvm/lib/AsmParser/LLLexer.cpp| 1 + llvm/lib/AsmParser/LLParser.cpp | 2 + llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp | 3 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/Target/X86/X86CallingConv.td | 18 llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 1 + llvm/lib/Target/X86/X86RegisterInfo.cpp | 4 + llvm/test/Bitcode/compatibility.ll| 2 + .../X86/dynamic-regmask-preserve-none.ll | 88 +++ llvm/test/CodeGen/X86/ipra-reg-usage.ll | 9 +- llvm/test/CodeGen/X86/ipra-transform.ll | 19 .../X86/preserve_nonecc64-ret-double.ll | 85 ++ llvm/test/CodeGen/X86/preserve_nonecc64.ll| 86 ++ 34 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/preserve-none-call-conv.c create mode 100644 llvm/test/CodeGen/X86/dynamic-regmask-preserve-none.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64-ret-double.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64.ll diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 64ab3378957c7..c241a8ccc7dfa 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2981,6 +2981,7 @@ enum CXCallingConv { CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, + CXCallingConv_PreserveNone = 20, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index db17211747b17..87e2ce91a0afb 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; + let Documentation = [PreserveNoneDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 98a7ecc7fd7df..a43e00c07e141 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,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
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/weiguozhi updated https://github.com/llvm/llvm-project/pull/76868 >From 90e14918a0eb13e2187f8548416ac72491d966c1 Mon Sep 17 00:00:00 2001 From: Guozhi Wei Date: Thu, 21 Dec 2023 19:04:44 + Subject: [PATCH 1/5] New calling convention preserve_none The new 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. --- clang/include/clang-c/Index.h | 1 + clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Basic/AttrDocs.td | 17 clang/include/clang/Basic/Specifiers.h| 1 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/Type.cpp| 2 + clang/lib/AST/TypePrinter.cpp | 6 ++ clang/lib/Basic/Targets/X86.h | 2 + clang/lib/CodeGen/CGCall.cpp | 4 + clang/lib/CodeGen/CGDebugInfo.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 7 ++ clang/lib/Sema/SemaType.cpp | 5 +- clang/test/CodeGen/debug-info-cc.c| 7 ++ clang/test/CodeGen/preserve-call-conv.c | 8 +- clang/test/Sema/no_callconv.cpp | 2 + clang/test/Sema/preserve-none-call-conv.c | 19 clang/tools/libclang/CXType.cpp | 1 + llvm/docs/LangRef.rst | 6 ++ llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/CallingConv.h| 3 + llvm/lib/AsmParser/LLLexer.cpp| 1 + llvm/lib/AsmParser/LLParser.cpp | 2 + llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp | 3 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/Target/X86/X86CallingConv.td | 18 llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 1 + llvm/lib/Target/X86/X86RegisterInfo.cpp | 4 + llvm/test/Bitcode/compatibility.ll| 2 + .../X86/dynamic-regmask-preserve-none.ll | 88 +++ llvm/test/CodeGen/X86/ipra-reg-usage.ll | 9 +- llvm/test/CodeGen/X86/ipra-transform.ll | 19 .../X86/preserve_nonecc64-ret-double.ll | 85 ++ llvm/test/CodeGen/X86/preserve_nonecc64.ll| 86 ++ 34 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/preserve-none-call-conv.c create mode 100644 llvm/test/CodeGen/X86/dynamic-regmask-preserve-none.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64-ret-double.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64.ll diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 64ab3378957c7..c241a8ccc7dfa 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2981,6 +2981,7 @@ enum CXCallingConv { CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, + CXCallingConv_PreserveNone = 20, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index db17211747b17..87e2ce91a0afb 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; + let Documentation = [PreserveNoneDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 98a7ecc7fd7df..a43e00c07e141 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,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
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/david-xl commented: Can you increase the test coverage: 1) preserve_none caller TAIL-calls preserve_none callee -- the tail call is preserved 2) regular function TAIL-calls preserve_none callee -- the tail call should be disabled and all CSRs should be saved/restored around the call. 3) preserve-none caller calls preserve_none callee -- no registers are saved/restored around the call 4) preserve_none caller calls preserve_none callee with long argument list -- CSRs used for arg passing. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/david-xl edited https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -1056,6 +1056,23 @@ def CC_Intel_OCL_BI : CallingConv<[ CCDelegateTo ]>; +def CC_X86_64_Preserve_None : CallingConv<[ + // We don't preserve general registers, so all of them can be used to pass + // arguments except + // - RBPframe pointer + // - R10'nest' parameter + // - RBXbase 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 weiguozhi wrote: @jyknight could you help to review the code that checks the combination of swift attributes and preserve_none in https://github.com/llvm/llvm-project/pull/76868/commits/dc1bc55634045adb5b0ab465b16dcf73f1e77144 https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; weiguozhi wrote: FunctionLike works for me. Thanks! https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -1056,6 +1056,23 @@ def CC_Intel_OCL_BI : CallingConv<[ CCDelegateTo ]>; +def CC_X86_64_Preserve_None : CallingConv<[ + // We don't preserve general registers, so all of them can be used to pass + // arguments except + // - RBPframe pointer + // - R10'nest' parameter + // - RBXbase pointer + // - R16 - R31 these are not available everywhere KanRobert wrote: I won't expect this from the name `preserve_none`. R16-R31 should be used to pas arguments when they're available. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -1056,6 +1056,23 @@ def CC_Intel_OCL_BI : CallingConv<[ CCDelegateTo ]>; +def CC_X86_64_Preserve_None : CallingConv<[ + // We don't preserve general registers, so all of them can be used to pass + // arguments except + // - RBPframe pointer + // - R10'nest' parameter + // - RBXbase 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 jyknight wrote: This delegation seems questionable -- what about the interaction with the swift attributes which use dedicated registers in CC_X86_64_C, which you're now also using for normal parameters? https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; weiguozhi wrote: I tried to add ``` let Subjects = SubjectList<[Function]>; ``` But it doesn't work for the code ``` void __attribute__((preserve_none)) boo(void *ptr) { } void (__attribute__((preserve_none)) *pboo1)(void *) = boo; ``` I got the error message ``` 'preserve_none' attribute only applies to functions ``` https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/erichkeane edited https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -1056,6 +1056,22 @@ def CC_Intel_OCL_BI : CallingConv<[ CCDelegateTo ]>; +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 weiguozhi wrote: Added a comment to mention that R16-R31 are not used to pass arguments because they are not universally available. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/weiguozhi updated https://github.com/llvm/llvm-project/pull/76868 >From 90e14918a0eb13e2187f8548416ac72491d966c1 Mon Sep 17 00:00:00 2001 From: Guozhi Wei Date: Thu, 21 Dec 2023 19:04:44 + Subject: [PATCH 1/2] New calling convention preserve_none The new 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. --- clang/include/clang-c/Index.h | 1 + clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Basic/AttrDocs.td | 17 clang/include/clang/Basic/Specifiers.h| 1 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/Type.cpp| 2 + clang/lib/AST/TypePrinter.cpp | 6 ++ clang/lib/Basic/Targets/X86.h | 2 + clang/lib/CodeGen/CGCall.cpp | 4 + clang/lib/CodeGen/CGDebugInfo.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 7 ++ clang/lib/Sema/SemaType.cpp | 5 +- clang/test/CodeGen/debug-info-cc.c| 7 ++ clang/test/CodeGen/preserve-call-conv.c | 8 +- clang/test/Sema/no_callconv.cpp | 2 + clang/test/Sema/preserve-none-call-conv.c | 19 clang/tools/libclang/CXType.cpp | 1 + llvm/docs/LangRef.rst | 6 ++ llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/CallingConv.h| 3 + llvm/lib/AsmParser/LLLexer.cpp| 1 + llvm/lib/AsmParser/LLParser.cpp | 2 + llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp | 3 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/Target/X86/X86CallingConv.td | 18 llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 1 + llvm/lib/Target/X86/X86RegisterInfo.cpp | 4 + llvm/test/Bitcode/compatibility.ll| 2 + .../X86/dynamic-regmask-preserve-none.ll | 88 +++ llvm/test/CodeGen/X86/ipra-reg-usage.ll | 9 +- llvm/test/CodeGen/X86/ipra-transform.ll | 19 .../X86/preserve_nonecc64-ret-double.ll | 85 ++ llvm/test/CodeGen/X86/preserve_nonecc64.ll| 86 ++ 34 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/preserve-none-call-conv.c create mode 100644 llvm/test/CodeGen/X86/dynamic-regmask-preserve-none.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64-ret-double.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64.ll diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 64ab3378957c70..c241a8ccc7dfac 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2981,6 +2981,7 @@ enum CXCallingConv { CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, + CXCallingConv_PreserveNone = 20, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index db17211747b17d..87e2ce91a0afb7 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; + let Documentation = [PreserveNoneDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 98a7ecc7fd7df3..a43e00c07e141d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,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
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -416,6 +416,12 @@ 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 floating-point weiguozhi wrote: > I suspect this should say any `non-general purpose registers (e.g. floating > point registers, on x86 XMMs/YMMs)`. Rather than `floating-point registers`. Thanks for the correction! Will change it. > Also isn't this just a hack to increase the number of registers used to pass > arguments? If so there has to be a better way of doing this. Maybe a > non-exposed attribute which is used only for non-exposed functions? e.g. on > x86 (not 64bit), regparm could be used internally there. It's not a hack, it's a natural extension. Because we don't preserve general registers, we can use all of them to pass arguments without the extra cost to save/restore those registers, they are clobbered by the function call anyway. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -1056,6 +1056,22 @@ def CC_Intel_OCL_BI : CallingConv<[ CCDelegateTo ]>; +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 KanRobert wrote: It does not mention R16-R31 https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
@@ -416,6 +416,12 @@ 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 floating-point pinskia wrote: I suspect this should say any `non-general purpose registers (e.g. floating point registers, on x86 XMMs/YMMs)`. Rather than `floating-point registers`. Also isn't this just a hack to increase the number of registers used to pass arguments? If so there has to be a better way of doing this. Maybe a non-exposed attribute which is used only for non-exposed functions? e.g. on x86 (not 64bit), regparm could be used internally there. https://github.com/llvm/llvm-project/pull/76868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] New calling convention preserve_none (PR #76868)
llvmbot wrote: @llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-clang Author: None (weiguozhi) Changes 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%. --- Patch is 39.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76868.diff 34 Files Affected: - (modified) clang/include/clang-c/Index.h (+1) - (modified) clang/include/clang/Basic/Attr.td (+5) - (modified) clang/include/clang/Basic/AttrDocs.td (+17) - (modified) clang/include/clang/Basic/Specifiers.h (+1) - (modified) clang/lib/AST/ItaniumMangle.cpp (+1) - (modified) clang/lib/AST/Type.cpp (+2) - (modified) clang/lib/AST/TypePrinter.cpp (+6) - (modified) clang/lib/Basic/Targets/X86.h (+2) - (modified) clang/lib/CodeGen/CGCall.cpp (+4) - (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+2) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+7) - (modified) clang/lib/Sema/SemaType.cpp (+4-1) - (modified) clang/test/CodeGen/debug-info-cc.c (+7) - (modified) clang/test/CodeGen/preserve-call-conv.c (+7-1) - (modified) clang/test/Sema/no_callconv.cpp (+2) - (added) clang/test/Sema/preserve-none-call-conv.c (+19) - (modified) clang/tools/libclang/CXType.cpp (+1) - (modified) llvm/docs/LangRef.rst (+6) - (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) - (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+1) - (modified) llvm/include/llvm/IR/CallingConv.h (+3) - (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) - (modified) llvm/lib/AsmParser/LLParser.cpp (+2) - (modified) llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp (+3) - (modified) llvm/lib/IR/AsmWriter.cpp (+1) - (modified) llvm/lib/Target/X86/X86CallingConv.td (+18) - (modified) llvm/lib/Target/X86/X86ISelLoweringCall.cpp (+1) - (modified) llvm/lib/Target/X86/X86RegisterInfo.cpp (+4) - (modified) llvm/test/Bitcode/compatibility.ll (+2) - (added) llvm/test/CodeGen/X86/dynamic-regmask-preserve-none.ll (+88) - (modified) llvm/test/CodeGen/X86/ipra-reg-usage.ll (+8-1) - (modified) llvm/test/CodeGen/X86/ipra-transform.ll (+19) - (added) llvm/test/CodeGen/X86/preserve_nonecc64-ret-double.ll (+85) - (added) llvm/test/CodeGen/X86/preserve_nonecc64.ll (+86) ``diff diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 64ab3378957c70..c241a8ccc7dfac 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2981,6 +2981,7 @@ enum CXCallingConv { CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, + CXCallingConv_PreserveNone = 20, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index db17211747b17d..87e2ce91a0afb7 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; + let Documentation = [PreserveNoneDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 98a7ecc7fd7df3..a43e00c07e141d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,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,
[llvm] [clang] New calling convention preserve_none (PR #76868)
https://github.com/weiguozhi created https://github.com/llvm/llvm-project/pull/76868 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%. >From 90e14918a0eb13e2187f8548416ac72491d966c1 Mon Sep 17 00:00:00 2001 From: Guozhi Wei Date: Thu, 21 Dec 2023 19:04:44 + Subject: [PATCH] New calling convention preserve_none The new 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. --- clang/include/clang-c/Index.h | 1 + clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Basic/AttrDocs.td | 17 clang/include/clang/Basic/Specifiers.h| 1 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/Type.cpp| 2 + clang/lib/AST/TypePrinter.cpp | 6 ++ clang/lib/Basic/Targets/X86.h | 2 + clang/lib/CodeGen/CGCall.cpp | 4 + clang/lib/CodeGen/CGDebugInfo.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 7 ++ clang/lib/Sema/SemaType.cpp | 5 +- clang/test/CodeGen/debug-info-cc.c| 7 ++ clang/test/CodeGen/preserve-call-conv.c | 8 +- clang/test/Sema/no_callconv.cpp | 2 + clang/test/Sema/preserve-none-call-conv.c | 19 clang/tools/libclang/CXType.cpp | 1 + llvm/docs/LangRef.rst | 6 ++ llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/CallingConv.h| 3 + llvm/lib/AsmParser/LLLexer.cpp| 1 + llvm/lib/AsmParser/LLParser.cpp | 2 + llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp | 3 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/Target/X86/X86CallingConv.td | 18 llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 1 + llvm/lib/Target/X86/X86RegisterInfo.cpp | 4 + llvm/test/Bitcode/compatibility.ll| 2 + .../X86/dynamic-regmask-preserve-none.ll | 88 +++ llvm/test/CodeGen/X86/ipra-reg-usage.ll | 9 +- llvm/test/CodeGen/X86/ipra-transform.ll | 19 .../X86/preserve_nonecc64-ret-double.ll | 85 ++ llvm/test/CodeGen/X86/preserve_nonecc64.ll| 86 ++ 34 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/preserve-none-call-conv.c create mode 100644 llvm/test/CodeGen/X86/dynamic-regmask-preserve-none.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64-ret-double.ll create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc64.ll diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 64ab3378957c70..c241a8ccc7dfac 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2981,6 +2981,7 @@ enum CXCallingConv { CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, + CXCallingConv_PreserveNone = 20, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index db17211747b17d..87e2ce91a0afb7 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2868,6 +2868,11 @@ def M68kRTD: DeclOrTypeAttr { let Documentation = [M68kRTDDocs]; } +def PreserveNone : DeclOrTypeAttr { + let Spellings = [Clang<"preserve_none">]; + let Documentation = [PreserveNoneDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td