[llvm-dev] variadic functions on X86_64 should (conditionally) save XMM regs even if -no-implicit-float
Anton Korobeynikov via llvm-dev
llvm-dev at lists.llvm.org
Wed May 29 19:01:35 PDT 2019
Apologies to hijack old thread, but it seems to receive no response.
It seems we're having 2 problems here and all of them are x86
specific. Here is quick overview of the problem: noimplicitfloat
should in theory prevent compiler to generate floating point
operations by itself. Currently it's used during optimizations and
codegen as follows:
- It inhibits some optimizations like vectorization
- It is used to determine optimal set of operations for things like
inlined memcpy / memset implementations
These features are common across middl-end and across various backends
(x86, arm, aarch64 and powepc includes).
However, x86 has one important difference: noimplicitfloat actually
*changes ABI*. Even more, it breaks varargs. Here is how: it is only
taken into account when receiving arguments. Essentially if we're
having varargs function, then it would force it to receive floating
point arguments on stack. However, no changes are made on caller side
– the floating point arguments are still passed in xmm registers.
Therefore even if we compile both caller and callee with
-mno-implicit-float we still will be unable to pass floating point
arguments properly. This is clearly a bug.
I believe that we indeed need to remove the noimplicitfloat case on callee side:
0. This fixes the longstanding bug.
1. We definitely should not change the ABI. And x86-64 ABI mandates us
to pass / receive floating point arguments in xmm registers.
2. There is no problem with kernel code with SSE2 unit disabled: the
use at callee side is guarded by an explicit check of # of fp
arguments (again, prescribed by ABI).
3. We're having explicit checks for no SSE2 cases here and there, so
-mno-sse / -mkernel / -msoft-float is unaffected
4. The use of floating point arguments should be considered as
"explicit use FP" and therefore should be allowed by the spirit of
5. We're having -mgeneral-regs-only these days, so more strict cases
are properly recognized as well.
PS: This fixes PR36507 and the fix is in https://reviews.llvm.org/D62639
On Mon, Nov 27, 2017 at 6:01 PM Nasser, Salim via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> Specifying -no-implicit-float prevents LLVM from using non-GPR registers for purely integer operations. This is useful for operating systems (such as Wind River's VxWorks) that support tasks that do not save all registers on context switch.
> This presents an interesting problem for variadic functions that may optionally take non-integer arguments (e.g. printf style functions). Should non-GPR registers be spilled to the stack when -no-implicit-float is specified?
> Ideally we would do so only if non-GPR register arguments are actually passed by the caller. This would require a runtime check, and whether or not such a check is feasible depends on the target and ABI.
> However for X86_64, the standard va_start code already has such a check - the number of vector (XMM) register arguments is stored in %al, and the code normally generated for variadic functions (in the absence of -no-implicit-float) includes a guard around the XMM spill code that checks for %al != 0.
> Therefore I believe it would be "in the spirit" of -no-implicit-float to remove the NoImplicitFloatOps check from the following:
> X86ISelLowering.cpp : get64BitArgumentXMMs()
> if (isSoftFloat || NoImplicitFloatOps || !Subtarget.hasSSE1())
> // Kernel mode asks for SSE to be disabled, so there are no XMM argument
> // registers.
> return None;
> Does this seem like a reasonable idea?
> Salim Nasser
> Wind River
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
With best regards, Anton Korobeynikov
Department of Statistical Modelling, Saint Petersburg State University
More information about the llvm-dev