Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ppc64(le): Add an option to use IEEE long double ABI on Linux #4833

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

liushuyu
Copy link
Contributor

@liushuyu liushuyu commented Feb 1, 2025

This pull request adds an option to use IEEE long double ABI on Linux (if the host environment supports it).

Some adjustments are made to accommodate the new ABI (glibc uses dual-ABI in this case, where new IEEE long double-capable functions are suffixed with __ieee128; older functions using IBM long double are also kept for compatibility reasons).

@liushuyu
Copy link
Contributor Author

liushuyu commented Feb 1, 2025

During the porting process, I discovered what seems to be an LLVM bug when targeting ppc64 using the IEEE long double ABI. Consider the following D code:

extern (C++) real test1(real arg0)
{
  if (!(arg0 == 0.0))
  {
    return 0.0;
  }
  else
  {
    return 0.0;
  }
}

LDC will generate the following LLVM IR (reduced, no optimization):

  target datalayout = "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
  target triple = "powerpc64le-unknown-linux-gnu"

  define fp128 @_Z5test1u9__ieee128(fp128 %0) {
    %2 = fcmp ogt fp128 %0, 0xL00000000000000000000000000000000
    %3 = icmp i1 %2, false
    br i1 %3, label %5, label %4

  4:                                                ; preds = %1
    ret fp128 0xL00000000000000000000000000000000

  5:                                                ; preds = %1
    ret fp128 0xL00000000000000000000000000000000
  }

... which will lead to what seems to be an infinite ppc-isel expansion loop inside LLVM.

I have added a workaround solution in this pull request to replace icmp .., false with xor .., true when lowering a "not" operator.

@JohanEngelen
Copy link
Member

During the porting process, I discovered what seems to be an LLVM bug when targeting ppc64 using the IEEE long double ABI.

Please also report the bug in LLVM's bug tracker.

Nice that you are working on this btw !

@@ -108,6 +108,8 @@ const char *getABI(const llvm::Triple &triple, const llvm::SmallVectorImpl<llvm:
return "elfv1";
if (ABIName.startswith("elfv2"))
return "elfv2";
if (ABIName.startswith("ieeelongdouble"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for a user to want to use ieeelongdouble together with elfv1 or 2? (seems logical, but I have no knowledge here)
If so, then this has to be rewritten to accept multiple options in mabi.

Copy link
Contributor Author

@liushuyu liushuyu Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like both Clang and GCC do support accepting multiple -mabi= values (only on ppc64 + big-endian systems, as ppc64le only supports elfv2).

However, GCC upstream wiki does mention ieeelongdouble + ppc64 + elfv1 is an unsupported configuration: https://gcc.gnu.org/wiki/Ieee128PowerPC#A7.0_Transition_to_IEEE_128-bit_floating_point_as_the_default_for_long_double

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed now, you can use -mabi=elfv1 -mabi=ieeelongdouble to enable IEEE long double on ppc64 (big-endian) systems. I have also added a logic where LDC will warn if this unsupported configuration is encountered.

driver/main.cpp Outdated
@@ -683,6 +683,10 @@ void registerPredefinedTargetVersions() {
if (triple.getOS() == llvm::Triple::Linux) {
VersionCondition::addPredefinedGlobalIdent(
triple.getArch() == llvm::Triple::ppc64 ? "ELFv1" : "ELFv2");
if (opts::mABI == "ieeelongdouble" && triple.isOSGlibc()) {
// Only GLibc needs this for IEEELongDouble
VersionCondition::addPredefinedGlobalIdent("D_PPCUseIEEE128");
Copy link
Member

@JohanEngelen JohanEngelen Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add D_PPCUseIEEE128 as reserved version identifier upstream (dmd). Helps compatibility with GDC too.

Edit: example PR: dlang/dmd#16773

Copy link
Contributor Author

@liushuyu liushuyu Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! However, I am not entirely sure if identifiers starting with D_ are already classified as somewhat reserved.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All identifiers starting with D_ are already reserved for the compiler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's good for documentation, and then you can sync/check with gdc too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe we should also forward the phobos changes to the D Language upstream? That way, GDC can also benefit from this fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good idea

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, which Phobos changes? And IMO real.mant_dig is all we need, as used in e.g. https://github.com/dlang/phobos/blob/c5d074b12e1038389401baa8c48c332fac5521e0/std/math/traits.d#L898-L1050

@@ -570,6 +570,8 @@ version (LDC)

version (AArch64) version = CheckFiberMigration;

version (PPC64) version = CheckFiberMigration;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intended change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is intended change. I fixed this after running the basic unit tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To add to my last comment, that issue was not discovered because the D Phobos library needs IEEE 128-bit arithmetic to work, which was not implemented before this pull request.

@JohanEngelen
Copy link
Member

would be good to add a lit testcase for setting this abi param

@liushuyu
Copy link
Contributor Author

liushuyu commented Feb 2, 2025

would be good to add a lit testcase for setting this abi param

Will do

@liushuyu
Copy link
Contributor Author

liushuyu commented Feb 4, 2025

During the porting process, I discovered what seems to be an LLVM bug when targeting ppc64 using the IEEE long double ABI.

Please also report the bug in LLVM's bug tracker.

Nice that you are working on this btw !

Thanks! I have proposed a fix to the LLVM upstream regarding this issue: llvm/llvm-project#125776

@liushuyu
Copy link
Contributor Author

liushuyu commented Feb 6, 2025

Corresponding DMD pull request: dlang/dmd#20826

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants