Is there anyway to force a C function on clang to be optimized even when the file is compiled with -O0
?
I'm looking for something equivalent to gcc's __attribute((optimize("s"))
or __attribute((optimize(3))
.
(Related: In clang, how do you use per-function optimization attributes?)
What I'm trying to do is generate certain functions in almost pure assembly via a macro—the remaining C code in there shouldn't generate any assembly code.
Ideally, the macro would use C-based integer constant expressions to choose which code to paste and writing static
before it would make the generate function static.
I also want no stack manipulation in the function's prologue.
On GCC something like:
enum { CONSTANT = 0 };
__attribute((optimize("Os"),noinline,noipa))
int foo(void){
if (CONSTANT) asm("mov $1, %eax; ret;");
else asm("xor %eax, %eax; ret;");
__builtin_unreachable();
}
gets the gist of it successfully.
On clang, the optimize
attribute is unrecognized and a push %rbp; mov %rsp, %rbp
prologue is generated which would break my real use case, as well as the ret
in this toy example, so it's most undesirable.
On GCC, __attribute((naked))
also works to eliminate the prologue and disable inlining and Inter-Procedural Analysis (IPA), but clang hard-rejects it, enforcing the requirement that naked functions should only consist of pure assembly (no nongenerating C code, even).
Per the GCC docs for x86 function attributes:
naked
This attribute allows the compiler to construct the requisite function declaration, while allowing the body of the function to be assembly code. The specified function will not have prologue/epilogue sequences generated by the compiler. Only basic asm statements can safely be included in naked functions (see Basic Asm). While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported.
While not supported, it was working well enough for my use-case. The hack with __attribute__((optimize("Os"),noinline,noipa))
is even more hacky but does in fact compile to the asm I want with current GCC. I'd like to do something similar with clang.