complex library functions (creal and cimag)

When I compile this code which includes call to crealf,

$ cat foo1.c
#include <complex.h>

float foo1(complex float z) { return crealf(z); }

clang emits a call to crealf,

$ clang foo1.c -S -o - -O3
foo1: # @foo1
.cfi_startproc

BB#0: # %entry

jmp crealf # TAILCALL

while gcc does it in two move instructions:

$ gcc foo1.c -S -o -O3
foo1:
.LFB0:
.cfi_startproc
movq %xmm0, -8(%rsp)
movss -8(%rsp), %xmm0

Is this an optimization which is missing in llvm?
Or is it making a deliberate decision not to expand the call to move instructions?

Missing optimization. There isn't any reason to avoid inlining the
implementation.

Probably the simplest place to implement this would be CGBuiltin in clang...

-Eli

It would also make sense to handle this in simplifylibcalls. There isn't anything C-specific about this.

-Chris

Please see the attached patches.

The first patch implements this optimization in SimplifyLibCalls.cpp.
I tried to accommodate all the different ways complex arguments are converted in clang/lib/CodeGen/TargetInfo.cpp, but I am pretty sure some of them haven’t been covered.

The second patch implements it in CGBuiltin.cpp. This one is much simpler than the first one.
The downside of this approach is that it only optimizes builtin functions. Also, the optimization is not available to non-clang front-ends.

Which one is the better approach?

I will resend the patch with a test case to llvm-commit if either one is acceptable.

simplifycreal.patch (4.37 KB)

builtincreal.patch (870 Bytes)