Skip to content

[RISCV] Enable GP relaxation for Linux#201265

Closed
wangpc-pp wants to merge 1 commit into
llvm:mainfrom
wangpc-pp:main-riscv-enable-gp-relax-on-linux
Closed

[RISCV] Enable GP relaxation for Linux#201265
wangpc-pp wants to merge 1 commit into
llvm:mainfrom
wangpc-pp:main-riscv-enable-gp-relax-on-linux

Conversation

@wangpc-pp
Copy link
Copy Markdown
Contributor

We have supported GP relaxation in https://reviews.llvm.org/D143673
for a long time, but we made it disabled by default.

This PR enables it in Clang driver when targeting Linux.

(Please remind me if I missed the context why we disabled it on Linux).

We have supported GP relaxation in https://reviews.llvm.org/D143673
for a long time, but we made it disabled by default.

This PR enables it in Clang driver when targeting Linux.

(Please remind me if I missed the context why we disabled it on Linux).
@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jun 3, 2026
@llvmorg-github-actions
Copy link
Copy Markdown

llvmorg-github-actions Bot commented Jun 3, 2026

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Pengcheng Wang (wangpc-pp)

Changes

We have supported GP relaxation in https://reviews.llvm.org/D143673
for a long time, but we made it disabled by default.

This PR enables it in Clang driver when targeting Linux.

(Please remind me if I missed the context why we disabled it on Linux).


Full diff: https://github.com/llvm/llvm-project/pull/201265.diff

4 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+10)
  • (modified) clang/test/Driver/riscv32-toolchain.c (+25)
  • (modified) clang/test/Driver/riscv64-toolchain.c (+25)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 132d9128a795b..d52076c037b76 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -812,6 +812,7 @@ RISC-V Support
 - Tenstorrent Ascalon D8 was renamed to Ascalon X. Use `tt-ascalon-x` with `-mcpu` or `-mtune`.
 - Intrinsics were added for the 'Zvabd` (RISC-V Integer Vector Absolute Difference) extension.
 - Intrinsics were added for the 'Zvzip` (Reordering Structured Data in Vector Registers) extension.
+- GP relaxation was enabled by default on Linux.
 
 CUDA/HIP Language Changes
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 131dd725c7289..5be5045ea6252 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -343,6 +343,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("--no-relax");
   }
 
+  // Default-enable LLD's --relax-gp for RISC-V on Linux when LLD is used and
+  // linker relaxation is not disabled by -mno-relax.
+  if (Triple.isRISCV() && Triple.isOSLinux()) {
+    bool IsLLD = false;
+    ToolChain.GetLinkerPath(&IsLLD);
+    if (IsLLD &&
+        Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
+      CmdArgs.push_back("--relax-gp");
+  }
+
   const bool IsShared = Args.hasArg(options::OPT_shared);
   if (IsShared)
     CmdArgs.push_back("-shared");
diff --git a/clang/test/Driver/riscv32-toolchain.c b/clang/test/Driver/riscv32-toolchain.c
index 04acf1e7edbe0..272e55c19df97 100644
--- a/clang/test/Driver/riscv32-toolchain.c
+++ b/clang/test/Driver/riscv32-toolchain.c
@@ -247,6 +247,31 @@
 // RUN:   | FileCheck -check-prefix=CHECK-RV32-GNU-RELAX %s
 // CHECK-RV32-GNU-RELAX-NOT: "--no-relax"
 
+/// Check that "--relax-gp" is forwarded to LLD for RISC-V on Linux by default.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-LLD-RELAXGP %s
+// CHECK-RV32-LLD-RELAXGP: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to GNU ld for RISC-V on Linux.
+// RUN: env "PATH=" %clang -### %s -fuse-ld=ld -no-pie \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-GNU-NO-RELAXGP %s
+// CHECK-RV32-GNU-NO-RELAXGP-NOT: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to LLD when -mno-relax is set.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie -mno-relax \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-LLD-NORELAX-NOGP %s
+// CHECK-RV32-LLD-NORELAX-NOGP: "--no-relax"
+// CHECK-RV32-LLD-NORELAX-NOGP-NOT: "--relax-gp"
+
 /// Check that "-static -pie" is forwarded to linker when "-static-pie" is used
 // RUN: %clang -static-pie -### %s -fuse-ld= \
 // RUN:   --target=riscv32-unknown-elf -rtlib=platform --unwindlib=platform \
diff --git a/clang/test/Driver/riscv64-toolchain.c b/clang/test/Driver/riscv64-toolchain.c
index 378f3d9db7bad..6820b1a34806d 100644
--- a/clang/test/Driver/riscv64-toolchain.c
+++ b/clang/test/Driver/riscv64-toolchain.c
@@ -203,6 +203,31 @@
 // RUN:   | FileCheck -check-prefix=CHECK-RV64-GNU-RELAX %s
 // CHECK-RV64-GNU-RELAX-NOT: "--no-relax"
 
+/// Check that "--relax-gp" is forwarded to LLD for RISC-V on Linux by default.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-LLD-RELAXGP %s
+// CHECK-RV64-LLD-RELAXGP: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to GNU ld for RISC-V on Linux.
+// RUN: env "PATH=" %clang -### %s -fuse-ld=ld -no-pie \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-GNU-NO-RELAXGP %s
+// CHECK-RV64-GNU-NO-RELAXGP-NOT: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to LLD when -mno-relax is set.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie -mno-relax \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-LLD-NORELAX-NOGP %s
+// CHECK-RV64-LLD-NORELAX-NOGP: "--no-relax"
+// CHECK-RV64-LLD-NORELAX-NOGP-NOT: "--relax-gp"
+
 /// Check that "-static -pie" is forwarded to linker when "-static-pie" is used
 // RUN: %clang -static-pie -### %s -fuse-ld= \
 // RUN:   --target=riscv64-unknown-elf -rtlib=platform --unwindlib=platform \

@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-backend-risc-v

Author: Pengcheng Wang (wangpc-pp)

Changes

We have supported GP relaxation in https://reviews.llvm.org/D143673
for a long time, but we made it disabled by default.

This PR enables it in Clang driver when targeting Linux.

(Please remind me if I missed the context why we disabled it on Linux).


Full diff: https://github.com/llvm/llvm-project/pull/201265.diff

4 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+10)
  • (modified) clang/test/Driver/riscv32-toolchain.c (+25)
  • (modified) clang/test/Driver/riscv64-toolchain.c (+25)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 132d9128a795b..d52076c037b76 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -812,6 +812,7 @@ RISC-V Support
 - Tenstorrent Ascalon D8 was renamed to Ascalon X. Use `tt-ascalon-x` with `-mcpu` or `-mtune`.
 - Intrinsics were added for the 'Zvabd` (RISC-V Integer Vector Absolute Difference) extension.
 - Intrinsics were added for the 'Zvzip` (Reordering Structured Data in Vector Registers) extension.
+- GP relaxation was enabled by default on Linux.
 
 CUDA/HIP Language Changes
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 131dd725c7289..5be5045ea6252 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -343,6 +343,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("--no-relax");
   }
 
+  // Default-enable LLD's --relax-gp for RISC-V on Linux when LLD is used and
+  // linker relaxation is not disabled by -mno-relax.
+  if (Triple.isRISCV() && Triple.isOSLinux()) {
+    bool IsLLD = false;
+    ToolChain.GetLinkerPath(&IsLLD);
+    if (IsLLD &&
+        Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
+      CmdArgs.push_back("--relax-gp");
+  }
+
   const bool IsShared = Args.hasArg(options::OPT_shared);
   if (IsShared)
     CmdArgs.push_back("-shared");
diff --git a/clang/test/Driver/riscv32-toolchain.c b/clang/test/Driver/riscv32-toolchain.c
index 04acf1e7edbe0..272e55c19df97 100644
--- a/clang/test/Driver/riscv32-toolchain.c
+++ b/clang/test/Driver/riscv32-toolchain.c
@@ -247,6 +247,31 @@
 // RUN:   | FileCheck -check-prefix=CHECK-RV32-GNU-RELAX %s
 // CHECK-RV32-GNU-RELAX-NOT: "--no-relax"
 
+/// Check that "--relax-gp" is forwarded to LLD for RISC-V on Linux by default.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-LLD-RELAXGP %s
+// CHECK-RV32-LLD-RELAXGP: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to GNU ld for RISC-V on Linux.
+// RUN: env "PATH=" %clang -### %s -fuse-ld=ld -no-pie \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-GNU-NO-RELAXGP %s
+// CHECK-RV32-GNU-NO-RELAXGP-NOT: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to LLD when -mno-relax is set.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie -mno-relax \
+// RUN:   --target=riscv32-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=ilp32 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV32-LLD-NORELAX-NOGP %s
+// CHECK-RV32-LLD-NORELAX-NOGP: "--no-relax"
+// CHECK-RV32-LLD-NORELAX-NOGP-NOT: "--relax-gp"
+
 /// Check that "-static -pie" is forwarded to linker when "-static-pie" is used
 // RUN: %clang -static-pie -### %s -fuse-ld= \
 // RUN:   --target=riscv32-unknown-elf -rtlib=platform --unwindlib=platform \
diff --git a/clang/test/Driver/riscv64-toolchain.c b/clang/test/Driver/riscv64-toolchain.c
index 378f3d9db7bad..6820b1a34806d 100644
--- a/clang/test/Driver/riscv64-toolchain.c
+++ b/clang/test/Driver/riscv64-toolchain.c
@@ -203,6 +203,31 @@
 // RUN:   | FileCheck -check-prefix=CHECK-RV64-GNU-RELAX %s
 // CHECK-RV64-GNU-RELAX-NOT: "--no-relax"
 
+/// Check that "--relax-gp" is forwarded to LLD for RISC-V on Linux by default.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-LLD-RELAXGP %s
+// CHECK-RV64-LLD-RELAXGP: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to GNU ld for RISC-V on Linux.
+// RUN: env "PATH=" %clang -### %s -fuse-ld=ld -no-pie \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-GNU-NO-RELAXGP %s
+// CHECK-RV64-GNU-NO-RELAXGP-NOT: "--relax-gp"
+
+/// Check that "--relax-gp" is NOT forwarded to LLD when -mno-relax is set.
+// RUN: %clang -### %s -fuse-ld=lld -B%S/Inputs/lld -no-pie -mno-relax \
+// RUN:   --target=riscv64-unknown-linux-gnu --rtlib=platform --unwindlib=platform -mabi=lp64 \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
+// RUN:   --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RV64-LLD-NORELAX-NOGP %s
+// CHECK-RV64-LLD-NORELAX-NOGP: "--no-relax"
+// CHECK-RV64-LLD-NORELAX-NOGP-NOT: "--relax-gp"
+
 /// Check that "-static -pie" is forwarded to linker when "-static-pie" is used
 // RUN: %clang -static-pie -### %s -fuse-ld= \
 // RUN:   --target=riscv64-unknown-elf -rtlib=platform --unwindlib=platform \

Comment on lines +346 to +354
// Default-enable LLD's --relax-gp for RISC-V on Linux when LLD is used and
// linker relaxation is not disabled by -mno-relax.
if (Triple.isRISCV() && Triple.isOSLinux()) {
bool IsLLD = false;
ToolChain.GetLinkerPath(&IsLLD);
if (IsLLD &&
Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
CmdArgs.push_back("--relax-gp");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we know in the driver if the intention is to create a shared library? If so, we should not pass --relax-gp, I don't think.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't know if we can just check if -static/-shared exists.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Passing the gp relax flag and sending it to -shared shouldn't cause any problems, since the linker mainly checks whether the __global_pointer$ symbol is defined and whether relocation is supported.

So I would incline just pass without checking it's -shared/-static/-fPIE/&$%^$^, that may just complicate the condition here.

@topperc
Copy link
Copy Markdown
Contributor

topperc commented Jun 3, 2026

The GP relaxation in lld only works for medlow without PIC. Linux defaults to PIE usually doesn't it?

@wangpc-pp
Copy link
Copy Markdown
Contributor Author

The GP relaxation in lld only works for medlow without PIC. Linux defaults to PIE usually doesn't it?

Get it. Does the gcc in OS distros also default to PIE?

@kito-cheng
Copy link
Copy Markdown
Member

The GP relaxation in lld only works for medlow without PIC. Linux defaults to PIE usually doesn't it?

Get it. Does the gcc in OS distros also default to PIE?

That depend on distro, but most distro are default to PIE.

Single command to check: gcc -v 2>&1|grep default-pie -i

@wangpc-pp
Copy link
Copy Markdown
Contributor Author

Should I proceed with this? TBH, GP relaxation doesn't make too many differences to code size and performance. I am just trying to fill the gap between Clang/LLD and GCC/Binutils.

@MaskRay
Copy link
Copy Markdown
Member

MaskRay commented Jun 4, 2026

Should I proceed with this? TBH, GP relaxation doesn't make too many differences to code size and performance. I am just trying to fill the gap between Clang/LLD and GCC/Binutils.

I prefer no. Note that hasShadowCallStack is also incompatible with GP relaxation. Another way to fill the gap is to change GCC/binutils defaults.

@wangpc-pp wangpc-pp closed this Jun 4, 2026
@wangpc-pp wangpc-pp deleted the main-riscv-enable-gp-relax-on-linux branch June 4, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants