__float128 (f128) calling convention bug on x86_64

Hello, I’m new to this mailing list and fixing llvm bugs for Android.

Can anyone point me to any previous discussion or work related to the following bug?
https://llvm.org/bugs/show_bug.cgi?id=23897

I am testing my patch to llvm to make f128 values stay in SSE registers instead of being split into two i64 values. I have tried to add a register class FR128 to hold f128 values for the x86_64 target. Preliminary tests seem to be working and compatible with gcc’s __float128 long double type.

I found that long double complex (with two f128 values) also have calling convention compatibility problem with gcc and can be fixed similarly.
My current patch does change quite a few places in type legalizing pass and some other optimizations related to f128 or i128 values. A few changes in the softening of floating point types to keep some f128 typed IR and convert some f128 opcode to library function calls.

Has anyone tried this approach or have other solution?

Thanks

– Chih-Hung

It sounds like you're on the right track for the low-level part of this.

The responsibility of matching platform ABI calling conventions is sort of
split across clang and LLVM. I think the way to get the calling convention
right is to change Clang to use x86_fp80 as the LLVM type for parameter and
return types, with some extra coercions inserted before calls and in
function prologues.

The mangling will need a separate change as it doesn't look at LLVM IR.

I found that long double complex (with two f128 values) also have calling
convention compatibility problem with gcc and can be fixed similarly.
My current patch does change quite a few places in type legalizing pass
and some other optimizations related to f128 or i128 values. A few changes
in the softening of floating point types to keep some f128 typed IR and
convert some f128 opcode to library function calls.

Has anyone tried this approach or have other solution?

It sounds like you're on the right track for the low-level part of this.

The responsibility of matching platform ABI calling conventions is sort of
split across clang and LLVM. I think the way to get the calling convention
right is to change Clang to use x86_fp80 as the LLVM type for parameter and
return types, with some extra coercions inserted before calls and in
function prologues.

The mangling will need a separate change as it doesn't look at LLVM IR.

I think you'll want to implement "useFloat128ManglingForLongDouble" for the
mangling change.

To be clear, what I plan to change is for the following C code:

long double foo1(long double x) { return x * x; }
long double _Complex foo2(long double _Complex x) { return x * x; }

on x86_64, when long double is mapped to f128, current LLVM IR:

define x86_fp80 @foo1(fp128 %x)
define { x86_fp80, x86_fp80 } @foo2({ fp128, fp128 }* byval align 16 %x)

to be changed to match gcc, and new LLVM IR:

define fp128 @foo1(fp128 %x)
define void @foo2({ fp128, fp128 }* noalias sret %agg.result, { fp128, fp128 }* byval align 16 %x)

I added a long double _Complex bug at
https://llvm.org/bugs/show_bug.cgi?id=24111