diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3189,6 +3189,8 @@ HelpText<"Disable function outlining (AArch64 only)">; def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group, HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">; +def mskip_rax_setup : Flag<["-"], "mskip-rax-setup">, Group, Flags<[NoXarchOption]>, + HelpText<"Skip setting up RAX register when passing variable arguments (x86 only)">; def mstackrealign : Flag<["-"], "mstackrealign">, Group, Flags<[CC1Option]>, HelpText<"Force realign the stack at entry to every function">, MarshallingInfoFlag>; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2194,6 +2194,11 @@ CmdArgs.push_back("-x86-asm-syntax=intel"); } + if (Args.hasArg(options::OPT_mskip_rax_setup)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-x86-skip-rax-setup"); + } + // Set flags to support MCU ABI. if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) { CmdArgs.push_back("-mfloat-abi"); diff --git a/clang/test/Driver/x86_features.c b/clang/test/Driver/x86_features.c --- a/clang/test/Driver/x86_features.c +++ b/clang/test/Driver/x86_features.c @@ -5,3 +5,6 @@ // Test that we don't produce an error with -mieee-fp. // RUN: %clang -### %s -mieee-fp -S 2>&1 | FileCheck --check-prefix=IEEE %s // IEEE-NOT: error: unknown argument + +// RUN: %clang -### %s -mskip-rax-setup -S 2>&1 | FileCheck --check-prefix=SRS %s +// SRS: "-mllvm" "-x86-skip-rax-setup" diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -93,6 +93,12 @@ "stores respectively."), cl::Hidden); +static cl::opt SkipRaxSetup( + "x86-skip-rax-setup", cl::init(false), + cl::desc("Skips setting up the RAX register when SSE is disabled and there " + "are no variable arguments passed in vector registers."), + cl::Hidden); + /// Call this when the user attempts to do something unsupported, like /// returning a double without SSE2 enabled on x86_64. This is not fatal, unlike /// report_fatal_error, so calling code should attempt to recover without @@ -4414,7 +4420,8 @@ } } - if (Is64Bit && isVarArg && !IsWin64 && !IsMustTail) { + if (Is64Bit && isVarArg && !IsWin64 && !IsMustTail && + (Subtarget.hasSSE1() || !SkipRaxSetup)) { // From AMD64 ABI document: // For calls that may call functions that use varargs or stdargs // (prototype-less calls or calls to functions containing ellipsis (...) in diff --git a/llvm/lib/Target/X86/pr23258.ll b/llvm/lib/Target/X86/pr23258.ll new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/X86/pr23258.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse | FileCheck %s --check-prefix=HAS-RAX +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-skip-rax-setup | FileCheck %s --check-prefix=HAS-RAX +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse -x86-skip-rax-setup | FileCheck %s --check-prefix=HAS-RAX +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=-sse -x86-skip-rax-setup | FileCheck %s --check-prefix=NO-RAX + +define dso_local void @foo() nounwind { +; HAS-RAX-LABEL: foo: +; HAS-RAX: # %bb.0: # %entry +; HAS-RAX-NEXT: movl $1, %edi +; HAS-RAX-NEXT: xorl %eax, %eax +; HAS-RAX-NEXT: jmp bar # TAILCALL +; +; NO-RAX-LABEL: foo: +; NO-RAX: # %bb.0: # %entry +; NO-RAX-NEXT: movl $1, %edi +; NO-RAX-NEXT: jmp bar # TAILCALL +entry: + tail call void (i32, ...) @bar(i32 1) + ret void +} + +declare dso_local void @bar(i32, ...)