LoongArch: Emit relocations even after .option norelax

Message ID 20260930071709.1426943-1-mengqinggang@loongson.cn
State New
Headers
Series LoongArch: Emit relocations even after .option norelax |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

mengqinggang Sept. 30, 2026, 7:17 a.m. UTC
  After .option norelax, a relocation that spans a relax fragment should
still be emitted, but GAS did not emit one.

The reason is that _loongarch_force_relocation_sub_same() uses
LARCH_opts.relax as a global gate and returns false immediately when
relaxation is disabled.

The fix removes the LARCH_opts.relax check from
_loongarch_force_relocation_sub_same() and instead uses the relocation's
coverage of a relax fragment to determine whether it should be emitted.

gas/
        * config/tc-loongarch.c (_loongarch_force_relocation_sub_same):
	Delete LARCH_opts.relax.
        * testsuite/gas/loongarch/relax-local-branch.s: New test.
        * testsuite/gas/loongarch/relax-local-branch.d: Likewise.
---
 gas/config/tc-loongarch.c                        |  3 ---
 gas/testsuite/gas/loongarch/relax-local-branch.d |  7 +++++++
 gas/testsuite/gas/loongarch/relax-local-branch.s | 11 +++++++++++
 3 files changed, 18 insertions(+), 3 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/relax-local-branch.d
 create mode 100644 gas/testsuite/gas/loongarch/relax-local-branch.s
  

Patch

diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index edbeac5e7d2..60caf4891c8 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1597,9 +1597,6 @@  _loongarch_force_relocation_sub_same (segT sec,
 				      fragS *addfrag,
 				      fragS *subfrag)
 {
-  if (!LARCH_opts.relax)
-    return false;
-
   /* Not emit relocation if section has no relaxable frag.  */
   if (!sec->sec_flg1)
     return false;
diff --git a/gas/testsuite/gas/loongarch/relax-local-branch.d b/gas/testsuite/gas/loongarch/relax-local-branch.d
new file mode 100644
index 00000000000..7d1eac42a8a
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax-local-branch.d
@@ -0,0 +1,7 @@ 
+#as: -mrelax
+#objdump: -dr
+
+#...
+[ 	]+28:[ 	]+53ffdbff[ 	]+b[ 	]+-40[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+28:[ 	]+R_LARCH_B26[ 	]+\.L1
+#pass
diff --git a/gas/testsuite/gas/loongarch/relax-local-branch.s b/gas/testsuite/gas/loongarch/relax-local-branch.s
new file mode 100644
index 00000000000..ee2514fccf2
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax-local-branch.s
@@ -0,0 +1,11 @@ 
+# Test that a local branch can still be relaxed at link time even when
+# relaxation is disabled for the branch instruction.
+
+.text
+.L1:
+  .option relax
+  call36 x
+  .align 5
+  add.d $t0, $t0, $t0
+  .option norelax
+  b .L1