This is an archive of the discontinued LLVM Phabricator instance.

Complex Long Double classification In RegCall calling convention
ClosedPublic

Authored by eandrews on Jul 11 2017, 8:39 AM.

Details

Summary

This change is part of the RegCall calling convention support for LLVM. Existing RegCall implementation was extended to include correct handling of Complex Long Double type. Complex long double types should be returned/passed in memory and not register stack. This patch implements this behavior.

Diff Detail

Repository
rL LLVM

Event Timeline

eandrews created this revision.Jul 11 2017, 8:39 AM
erichkeane edited edge metadata.Jul 11 2017, 8:54 AM

Oren discovered this miss to the original implementation. I'd reviewed this internally quite a bit.

The reason for the Win32ABI test is that MSVC 'long double' is actually small enough for SSE registers in this case. I DO now (looking again, sorry Elizabeth) wonder if there is a better way to exclude extended-length LongDouble type? Could we us the 'length' of it instead? @rnk : opinion?

rnk edited edge metadata.Jul 11 2017, 10:05 AM

Oren discovered this miss to the original implementation. I'd reviewed this internally quite a bit.

The reason for the Win32ABI test is that MSVC 'long double' is actually small enough for SSE registers in this case. I DO now (looking again, sorry Elizabeth) wonder if there is a better way to exclude extended-length LongDouble type? Could we us the 'length' of it instead? @rnk : opinion?

Yeah, you can ask clang::TargetInfo for the format of most basic FP types. The code to do that looks like:

&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended()

Any reason you can't just add that condition to isX86VectorTypeForVectorCall? I assume we don't want to pass x86_fp80s in SSE registers for vectorcall either, right? That would eliminate the need for the isRegCallReturnableHA helper and the IsWin32StructABI parameter, which is a poorly named variable.

In D35259#805409, @rnk wrote:

Oren discovered this miss to the original implementation. I'd reviewed this internally quite a bit.

The reason for the Win32ABI test is that MSVC 'long double' is actually small enough for SSE registers in this case. I DO now (looking again, sorry Elizabeth) wonder if there is a better way to exclude extended-length LongDouble type? Could we us the 'length' of it instead? @rnk : opinion?

Yeah, you can ask clang::TargetInfo for the format of most basic FP types. The code to do that looks like:

&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended()

Any reason you can't just add that condition to isX86VectorTypeForVectorCall? I assume we don't want to pass x86_fp80s in SSE registers for vectorcall either, right? That would eliminate the need for the isRegCallReturnableHA helper and the IsWin32StructABI parameter, which is a poorly named variable.

It actually WOULD make sense to apply this to vectorcall as well, wouldn't it? I presumed we didnt want to change its behavior, however vectorcall is MSVC-only (other than us), so the long-double issue isn't a thing over there.@eandrews?

In D35259#805409, @rnk wrote:

Oren discovered this miss to the original implementation. I'd reviewed this internally quite a bit.

The reason for the Win32ABI test is that MSVC 'long double' is actually small enough for SSE registers in this case. I DO now (looking again, sorry Elizabeth) wonder if there is a better way to exclude extended-length LongDouble type? Could we us the 'length' of it instead? @rnk : opinion?

Yeah, you can ask clang::TargetInfo for the format of most basic FP types. The code to do that looks like:

&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended()

Any reason you can't just add that condition to isX86VectorTypeForVectorCall? I assume we don't want to pass x86_fp80s in SSE registers for vectorcall either, right? That would eliminate the need for the isRegCallReturnableHA helper and the IsWin32StructABI parameter, which is a poorly named variable.

It actually WOULD make sense to apply this to vectorcall as well, wouldn't it? I presumed we didnt want to change its behavior, however vectorcall is MSVC-only (other than us), so the long-double issue isn't a thing over there.@eandrews?

I can apply this condition to isX86VectorTypeForVectorCall like Reid suggested. The only reason I did not do that originally was because I wasn't sure how to differentiate between the calling conventions without changing function declaration. If I don't need to explicitly differentiate between RegCall and VectorCall and can use the 'length' instead, I think this works better. Like Reid mentioned, it would eliminate the need for isRegCallReturnableHA and IsWin32StructABI.

eandrews updated this revision to Diff 107343.Jul 19 2017, 10:55 AM

As per revision comments, I moved the condition for extended precision floating type to isX86VectorTypeForVectorCall. This update will now alter behavior for complex long double type under vectorcall calling convention as well. Returns/parameters will be passed in memory.

rnk added inline comments.Jul 19 2017, 11:48 AM
lib/CodeGen/TargetInfo.cpp
3516 ↗(On Diff #107343)

This is incorrect. We should consult the CXXABI first, and then only do these regcall-specific things if it returns false. Consider adding this test case to find the bug:

struct NonTrivial {
  int x, y;
  ~NonTrivial();
};
NonTrivial __regcall f() { return NonTrivial(); }

This should not return in registers, but it does today.

3526 ↗(On Diff #107343)

This isn't necessarily a bug, but please always do C++ ABI classifications first so it's easy to spot the bug above.

eandrews updated this revision to Diff 107667.Jul 21 2017, 6:49 AM

Regcall-specific checks for Lin64 now occur only if CXXABI returns false. An existing test has also been modified to verify behavior with non trivial destructors.

rnk accepted this revision.Jul 21 2017, 10:59 AM

lgtm

This revision is now accepted and ready to land.Jul 21 2017, 10:59 AM
This revision was automatically updated to reflect the committed changes.